diff --git a/USER_GUIDE.md b/USER_GUIDE.md index cce234bb3e..eb498cfc71 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -198,6 +198,7 @@ You can find a working sample of the above code in [IndexingBasics.java](./sampl - [Data Stream APIs](./guides/data_stream.md) - [Point-in-Time APIs](./guides/point_in_time.md) - [Search](./guides/search.md) +- [Generic Client](./guides/generic.md) ## Plugins diff --git a/guides/generic.md b/guides/generic.md new file mode 100644 index 0000000000..3ecebcab3b --- /dev/null +++ b/guides/generic.md @@ -0,0 +1,79 @@ +- [Generic Client](#generic-client) + - [Getting the Client](#get-client) + - [Sending Simple Requests](#request-bodyless) + - [Sending JSON Requests](#request-json) + - [Sending JSON using POJOs](#request-pojo) + +# Generic Client + +There are rare circumstances when the typed OpenSearch client APIs are too constraining and there is a need to communicate with OpenSearch cluster (or individual nodes) over generic HTTP request / response communication. The `OpenSearchGenericClient` could be used in such cases. + +## Getting the Client +The following sample code gets the `OpenSearchGenericClient` rom the `OpenSearchClient` instance. + +```java +final OpenSearchGenericClient generic = javaClient().generic(); +``` + +## Sending Simple Request +The following sample code sends a simple request that does not require any payload to be provided. + +```java +// compare with what the low level client outputs +try (Response response = javaClient().generic().execute(Requests.builder().endpoint("/").method("GET").build())) { + // ... +} +``` + +Please notice that the `Response` instance should be closed explicitly in order to free up any allocated resource (like response input streams or buffers). The generic client never interprets status codes and provides the direct access to the response as it was received from the server. This is responsibility of the caller to decide what should happen in case of unsuccessful invocations. + +## Sending JSON Requests +The following sample code a simple request with JSON body. + +```java + try (Response response = javaClient().generic() + .execute( + Requests.builder() + .endpoint("/" + index + "/_search") + .method("POST") + .json("{" + + " \"query\": {" + + " \"match_all\": {}" + + " }" + + "}" + ) + .build())) { + // Retrieve the response body as a simple string + final String body = response.getBody().map(Body::getAsString).orElse(""); + // ... +} +``` + +## Sending JSON using POJOs +Besides providing the ability to deal with raw request and response payloads (bodies), the `OpenSearchGenericClient` could be used mixed with existing OpenSearch typed requests and responses (POJOs), like the following sample code demonstrates. + + +```java +final JsonpMapper jsonpMapper = javaClient()._transport().jsonpMapper(); + +final CreateIndexRequest request = CreateIndexRequest.of( + b -> b.index(index) + .mappings( + m -> m.properties("name", Property.of(p -> p.keyword(v -> v.docValues(true)))) + .properties("size", Property.of(p -> p.keyword(v -> v.docValues(true)))) + ) + .settings(settings -> settings.sort(s -> s.field("name").order(SegmentSortOrder.Asc))) +); + +try (Response response = javaClient().generic() + .execute( + Requests.builder() + .endpoint("/" + index).method("PUT") + .json(request, jsonpMapper).build())) { + // Retrieve the response body as a POJO + final CreateIndexResponse r = response.getBody() + .map(b -> Bodies.json(b, CreateIndexResponse._DESERIALIZER, jsonpMapper)) + .orElse(null); + // ... +} +``` \ No newline at end of file diff --git a/java-client/src/main/java/org/opensearch/client/opensearch/generic/Bodies.java b/java-client/src/main/java/org/opensearch/client/opensearch/generic/Bodies.java index 65921a41df..76ba65cd4d 100644 --- a/java-client/src/main/java/org/opensearch/client/opensearch/generic/Bodies.java +++ b/java-client/src/main/java/org/opensearch/client/opensearch/generic/Bodies.java @@ -37,8 +37,8 @@ public static Body json(C value, JsonpMapper jsonpMapper) throws IOException try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { try (JsonGenerator generator = jsonpMapper.jsonProvider().createGenerator(baos)) { jsonpMapper.serialize(value, generator); - return Body.from(baos.toByteArray(), APPLICATION_JSON); } + return Body.from(baos.toByteArray(), APPLICATION_JSON); } } diff --git a/java-client/src/test/java11/org/opensearch/client/opensearch/integTest/AbstractGenericClientIT.java b/java-client/src/test/java11/org/opensearch/client/opensearch/integTest/AbstractGenericClientIT.java index 4857e81d8d..76211659c1 100644 --- a/java-client/src/test/java11/org/opensearch/client/opensearch/integTest/AbstractGenericClientIT.java +++ b/java-client/src/test/java11/org/opensearch/client/opensearch/integTest/AbstractGenericClientIT.java @@ -15,11 +15,15 @@ import java.util.stream.Collectors; import org.junit.Test; import org.opensearch.client.json.JsonpDeserializer; +import org.opensearch.client.json.JsonpMapper; +import org.opensearch.client.opensearch._types.mapping.Property; import org.opensearch.client.opensearch.core.SearchResponse; import org.opensearch.client.opensearch.generic.Bodies; import org.opensearch.client.opensearch.generic.Requests; import org.opensearch.client.opensearch.generic.Response; +import org.opensearch.client.opensearch.indices.CreateIndexRequest; import org.opensearch.client.opensearch.indices.CreateIndexResponse; +import org.opensearch.client.opensearch.indices.SegmentSortOrder; public abstract class AbstractGenericClientIT extends OpenSearchJavaClientTestCase { @@ -113,6 +117,14 @@ private void createTestDocument(String index, String id, ShopItem document) thro } private void createIndex(String index) throws IOException { + if (randomBoolean()) { + createIndexUntyped(index); + } else { + createIndexTyped(index); + } + } + + private void createIndexUntyped(String index) throws IOException { try ( Response response = javaClient().generic() .execute( @@ -147,11 +159,36 @@ private void createIndex(String index) throws IOException { assertThat(response.getStatus(), equalTo(200)); assertThat(response.getBody().isPresent(), equalTo(true)); - final CreateIndexResponse r = Bodies.json( - response.getBody().get(), - CreateIndexResponse._DESERIALIZER, - javaClient()._transport().jsonpMapper() - ); + final CreateIndexResponse r = response.getBody() + .map(b -> Bodies.json(b, CreateIndexResponse._DESERIALIZER, javaClient()._transport().jsonpMapper())) + .orElse(null); + assertThat(r.acknowledged(), equalTo(true)); + } + + createTestDocuments(index); + refreshIndex(index); + } + + private void createIndexTyped(String index) throws IOException { + final JsonpMapper jsonpMapper = javaClient()._transport().jsonpMapper(); + + final CreateIndexRequest request = CreateIndexRequest.of( + b -> b.index(index) + .mappings( + m -> m.properties("name", Property.of(p -> p.keyword(v -> v.docValues(true)))) + .properties("size", Property.of(p -> p.keyword(v -> v.docValues(true)))) + ) + .settings(settings -> settings.sort(s -> s.field("name").order(SegmentSortOrder.Asc))) + ); + + try ( + Response response = javaClient().generic() + .execute(Requests.builder().endpoint("/" + index).method("PUT").json(request, jsonpMapper).build()) + ) { + assertThat(response.getStatus(), equalTo(200)); + assertThat(response.getBody().isPresent(), equalTo(true)); + + final CreateIndexResponse r = Bodies.json(response.getBody().get(), CreateIndexResponse._DESERIALIZER, jsonpMapper); assertThat(r.acknowledged(), equalTo(true)); } diff --git a/java-client/src/test/java11/org/opensearch/client/opensearch/integTest/AbstractSearchTemplateRequestIT.java b/java-client/src/test/java11/org/opensearch/client/opensearch/integTest/AbstractSearchTemplateRequestIT.java index 4489ef8a68..efa2298046 100644 --- a/java-client/src/test/java11/org/opensearch/client/opensearch/integTest/AbstractSearchTemplateRequestIT.java +++ b/java-client/src/test/java11/org/opensearch/client/opensearch/integTest/AbstractSearchTemplateRequestIT.java @@ -89,7 +89,6 @@ public void testTemplateSearchAggregations() throws Exception { @Test public void testMultiSearchTemplate() throws Exception { - System.out.println("Multi search template test"); var index = "test-msearch-template"; createDocuments(index);