This is an automated email from the ASF dual-hosted git repository. pdallig pushed a commit to branch branch-0.12 in repository https://gitbox.apache.org/repos/asf/zeppelin.git
The following commit(s) were added to refs/heads/branch-0.12 by this push: new f632ca27b8 [ZEPPELIN-6192] Enhance getHit() safety in ActionResponse and improve interface documentation f632ca27b8 is described below commit f632ca27b88eab52d91e150bf7d5a10bff99f132 Author: Gyeongtae Park <67095975+parkgyeong...@users.noreply.github.com> AuthorDate: Fri Jun 27 05:05:51 2025 +0900 [ZEPPELIN-6192] Enhance getHit() safety in ActionResponse and improve interface documentation ### What is this PR for? This PR improves the robustness and clarity of the Elasticsearch interpreter module in Zeppelin. - Reimplemented `ActionResponse#getHit()` to throw `NoSuchElementException` instead of relying on unchecked access to the first hit. - Introduced a new method `getFirstHit()` which returns an `Optional<HitWrapper>` for safer optional access. - Added and refined Javadoc comments in: - `ActionResponse.java` for both `getHit()` and `getFirstHit()` - `ElasticsearchClient.java` to improve clarity on interface usage ### What type of PR is it? Documentation Refactoring ### Todos * [x] Refactor `getHit()` to throw a safe exception * [x] Add `getFirstHit()` method using `Optional` ### What is the Jira issue? * https://issues.apache.org/jira/browse/ZEPPELIN/ZEPPELIN-6192 ### How should this be tested? * Build Test * Elasticsearch Interpreter Test ### Screenshots (if appropriate) ### Questions: * Does the license files need to update? No. * Is there breaking changes for older versions? No. * Does this needs documentation? No. Closes #4940 from ParkGyeongTae/enhance-getHit-safety. Signed-off-by: Philipp Dallig <philipp.dal...@gmail.com> (cherry picked from commit fd7631e4f276e175df6d04bb1513059808751c7d) Signed-off-by: Philipp Dallig <philipp.dal...@gmail.com> --- .../elasticsearch/action/ActionResponse.java | 36 +++++++++++++- .../elasticsearch/client/ElasticsearchClient.java | 55 +++++++++++++++++++++- 2 files changed, 88 insertions(+), 3 deletions(-) diff --git a/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/action/ActionResponse.java b/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/action/ActionResponse.java index 4141bce661..6ede07fde1 100644 --- a/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/action/ActionResponse.java +++ b/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/action/ActionResponse.java @@ -19,9 +19,22 @@ package org.apache.zeppelin.elasticsearch.action; import java.util.LinkedList; import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; /** - * Contains the result of an action (hits, aggregations, ...). + * A response object representing the result of an Elasticsearch action + * (such as document retrieval, search, or aggregation). + * + * <p> + * This class is used internally by the Zeppelin Elasticsearch interpreter + * to store the result of interactions with Elasticsearch. + * It holds basic metadata like success status, total number of hits, + * a list of search hits, and a list of aggregations. + * </p> + * + * @see HitWrapper + * @see AggWrapper */ public class ActionResponse { @@ -72,7 +85,26 @@ public class ActionResponse { return this; } + /** + * Returns the first hit in the search result. + * + * @return the first {@link HitWrapper} in the list + * @throws NoSuchElementException if there are no hits in the response + */ public HitWrapper getHit() { - return this.hits.get(0); + return getFirstHit() + .orElseThrow(() -> new NoSuchElementException("No hit found in ActionResponse")); + } + + /** + * Returns the first hit in the search result, if it exists. + * + * <p>If there are no hits, returns {@code Optional.empty()}.</p> + * + * @return an {@code Optional} containing the first {@link HitWrapper}, or empty if the hit + * list is empty + */ + public Optional<HitWrapper> getFirstHit() { + return hits.isEmpty() ? Optional.empty() : Optional.of(hits.get(0)); } } diff --git a/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/client/ElasticsearchClient.java b/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/client/ElasticsearchClient.java index 48e1980610..e503773573 100644 --- a/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/client/ElasticsearchClient.java +++ b/elasticsearch/src/main/java/org/apache/zeppelin/elasticsearch/client/ElasticsearchClient.java @@ -20,17 +20,70 @@ package org.apache.zeppelin.elasticsearch.client; import org.apache.zeppelin.elasticsearch.action.ActionResponse; /** - * Interface that must be implemented by any kind of Elasticsearch client (transport, ...). + * Interface defining a contract for Elasticsearch client implementations. + * <p> + * Implementations may use Transport Client (deprecated), High Level REST Client, + * or the new Elasticsearch Java API Client. + * </p> + * + * <p> + * This interface is intended to abstract the underlying Elasticsearch connection + * mechanism, allowing Zeppelin interpreters to interact with different versions + * of Elasticsearch transparently. + * </p> + * + * @see org.apache.zeppelin.elasticsearch.action.ActionResponse */ public interface ElasticsearchClient { + /** + * Retrieves a document by its ID. + * + * @param index The index name. + * @param type The document type. (Note: deprecated in Elasticsearch 7+, use "_doc") + * @param id The unique document ID. + * @return The response containing the document if found, or an error response. + */ ActionResponse get(String index, String type, String id); + /** + * Indexes a document (insert or update). + * + * @param index The index name. + * @param type The document type. + * @param id The document ID. If null, a random ID may be generated depending on + * implementation. + * @param data The JSON string of the document to index. + * @return The response indicating success or failure. + */ ActionResponse index(String index, String type, String id, String data); + /** + * Deletes a document by its ID. + * + * @param index The index name. + * @param type The document type. + * @param id The document ID to delete. + * @return The response indicating result of the deletion. + */ ActionResponse delete(String index, String type, String id); + /** + * Executes a search query on one or more indices and types. + * + * @param indices Array of index names to search. + * @param types Array of document types to search (can be null or ["_doc"] in ES 7+). + * @param query The raw JSON query string. + * @param size Maximum number of documents to return. + * @return The response containing the search hits. + */ ActionResponse search(String[] indices, String[] types, String query, int size); + /** + * Closes any open connections and cleans up resources. + * <p> + * Must be called when the client is no longer needed. + * </p> + */ void close(); }