From e6984a0145edf14a913d3f01100bf07d8d06d65e Mon Sep 17 00:00:00 2001 From: Karthik Subramanian Date: Sun, 22 Oct 2023 18:33:00 -0400 Subject: [PATCH 1/4] Fix for #176 Signed-off-by: Karthik Subramanian --- .../client/json/JsonpDeserializerBase.java | 9 +++- .../json/JsonpDeserializerBaseTest.java | 45 +++++++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) create mode 100644 java-client/src/test/java/org/opensearch/client/opensearch/json/JsonpDeserializerBaseTest.java diff --git a/java-client/src/main/java/org/opensearch/client/json/JsonpDeserializerBase.java b/java-client/src/main/java/org/opensearch/client/json/JsonpDeserializerBase.java index df405110eb..bc8da85c58 100644 --- a/java-client/src/main/java/org/opensearch/client/json/JsonpDeserializerBase.java +++ b/java-client/src/main/java/org/opensearch/client/json/JsonpDeserializerBase.java @@ -335,8 +335,13 @@ public List deserialize(JsonParser parser, JsonpMapper mapper, Event event) { if (event == Event.START_ARRAY) { List result = new ArrayList<>(); while ((event = parser.next()) != Event.END_ARRAY) { - JsonpUtils.ensureAccepts(itemDeserializer, parser, event); - result.add(itemDeserializer.deserialize(parser, mapper, event)); + // JSON null: add null unless the deserializer can handle it + if (event == Event.VALUE_NULL && !itemDeserializer.accepts(event)) { + result.add(null); + } else { + JsonpUtils.ensureAccepts(itemDeserializer, parser, event); + result.add(itemDeserializer.deserialize(parser, mapper, event)); + } } return result; } else { diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/json/JsonpDeserializerBaseTest.java b/java-client/src/test/java/org/opensearch/client/opensearch/json/JsonpDeserializerBaseTest.java new file mode 100644 index 0000000000..a58060a142 --- /dev/null +++ b/java-client/src/test/java/org/opensearch/client/opensearch/json/JsonpDeserializerBaseTest.java @@ -0,0 +1,45 @@ +package org.opensearch.client.opensearch.json; + +import jakarta.json.stream.JsonParser; +import org.junit.Test; +import org.opensearch.client.json.JsonpDeserializer; +import org.opensearch.client.opensearch._types.FieldValue; +import org.opensearch.client.opensearch.model.ModelTestCase; + +import java.io.StringReader; +import java.util.List; + + +public class JsonpDeserializerBaseTest extends ModelTestCase { + + @Test + public void testNullArrayItem() { + + String json = "[\"a\", null, \"c\"]"; + + // Types that don't accept null events should end up as null values in the list + { + JsonpDeserializer stringDeser = JsonpDeserializer.stringDeserializer(); + assertFalse(stringDeser.accepts(JsonParser.Event.VALUE_NULL)); + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + + List stringList = JsonpDeserializer.arrayDeserializer(stringDeser).deserialize(parser, mapper); + assertEquals("a", stringList.get(0)); + assertNull(stringList.get(1)); + assertEquals("c", stringList.get(2)); + } + + // Types that do accept null events should end up as their null representation + { + assertTrue(FieldValue._DESERIALIZER.accepts(JsonParser.Event.VALUE_NULL)); + + JsonParser parser = mapper.jsonProvider().createParser(new StringReader(json)); + List valueList = JsonpDeserializer.arrayDeserializer(FieldValue._DESERIALIZER).deserialize(parser, mapper); + + assertEquals("a", valueList.get(0)._get()); + assertTrue(valueList.get(1).isNull()); + assertEquals("c", valueList.get(2)._get()); + } + } +} From 7049c1246ae605f576a79ae30cf56a3197477079 Mon Sep 17 00:00:00 2001 From: Karthik Subramanian Date: Sun, 22 Oct 2023 18:48:55 -0400 Subject: [PATCH 2/4] Updated CHANGELOG.md & fixed format violation Signed-off-by: Karthik Subramanian --- CHANGELOG.md | 1 + .../client/opensearch/json/JsonpDeserializerBaseTest.java | 6 ++---- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dac2b79946..4b7c5f1ce4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ This section is for maintaining a changelog for all breaking changes for the cli ### Dependencies ### Changed +- Allow null values in arrays ([#679](https://github.com/opensearch-project/opensearch-java/pull/679)) ### Deprecated diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/json/JsonpDeserializerBaseTest.java b/java-client/src/test/java/org/opensearch/client/opensearch/json/JsonpDeserializerBaseTest.java index a58060a142..400696f429 100644 --- a/java-client/src/test/java/org/opensearch/client/opensearch/json/JsonpDeserializerBaseTest.java +++ b/java-client/src/test/java/org/opensearch/client/opensearch/json/JsonpDeserializerBaseTest.java @@ -1,15 +1,13 @@ package org.opensearch.client.opensearch.json; import jakarta.json.stream.JsonParser; +import java.io.StringReader; +import java.util.List; import org.junit.Test; import org.opensearch.client.json.JsonpDeserializer; import org.opensearch.client.opensearch._types.FieldValue; import org.opensearch.client.opensearch.model.ModelTestCase; -import java.io.StringReader; -import java.util.List; - - public class JsonpDeserializerBaseTest extends ModelTestCase { @Test From 2b7ea083cfa373c79377ddcd3f015ff5682b80cf Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 11:13:07 -0400 Subject: [PATCH 3/4] Bump org.owasp.dependencycheck from 8.4.0 to 8.4.2 (#680) * Bump org.owasp.dependencycheck from 8.4.0 to 8.4.2 Bumps org.owasp.dependencycheck from 8.4.0 to 8.4.2. --- updated-dependencies: - dependency-name: org.owasp.dependencycheck dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] * Update changelog Signed-off-by: dependabot[bot] --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: dependabot[bot] Signed-off-by: Karthik Subramanian --- CHANGELOG.md | 1 + java-client/build.gradle.kts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b7c5f1ce4..c63d34a092 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Inspired from [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) ## [Unreleased 3.0] ### Dependencies - Bumps `io.github.classgraph:classgraph` from 4.8.162 to 4.8.163 +- Bumps `org.owasp.dependencycheck` from 8.4.0 to 8.4.2 This section is for maintaining a changelog for all breaking changes for the client that cannot be released in the 2.x line. All other non-breaking changes should be added to [Unreleased 2.x] section. diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts index 0b1247b325..6c9a52e4a5 100644 --- a/java-client/build.gradle.kts +++ b/java-client/build.gradle.kts @@ -51,7 +51,7 @@ plugins { `java-library` `maven-publish` id("com.github.jk1.dependency-license-report") version "2.5" - id("org.owasp.dependencycheck") version "8.4.0" + id("org.owasp.dependencycheck") version "8.4.2" id("com.diffplug.spotless") version "6.22.0" } apply(plugin = "opensearch.repositories") From 658660e1a9043ea533021c191b1359b527affb47 Mon Sep 17 00:00:00 2001 From: Andriy Redko Date: Mon, 23 Oct 2023 13:23:32 -0400 Subject: [PATCH 4/4] Add basic Search API integration test (#678) Signed-off-by: Andriy Redko Signed-off-by: Karthik Subramanian --- .../integTest/AbstractSearchRequestIT.java | 132 ++++++++++++++++++ .../httpclient5/SearchRequestIT.java | 13 ++ .../integTest/restclient/SearchRequestIT.java | 24 ++++ 3 files changed, 169 insertions(+) create mode 100644 java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractSearchRequestIT.java create mode 100644 java-client/src/test/java/org/opensearch/client/opensearch/integTest/httpclient5/SearchRequestIT.java create mode 100644 java-client/src/test/java/org/opensearch/client/opensearch/integTest/restclient/SearchRequestIT.java diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractSearchRequestIT.java b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractSearchRequestIT.java new file mode 100644 index 0000000000..96ee498894 --- /dev/null +++ b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/AbstractSearchRequestIT.java @@ -0,0 +1,132 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.client.opensearch.integTest; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.arrayContaining; +import static org.hamcrest.Matchers.hasSize; + +import java.io.IOException; +import org.junit.Test; +import org.opensearch.client.opensearch._types.FieldValue; +import org.opensearch.client.opensearch._types.SortOrder; +import org.opensearch.client.opensearch._types.mapping.Property; +import org.opensearch.client.opensearch._types.query_dsl.Query; +import org.opensearch.client.opensearch._types.query_dsl.TermQuery; +import org.opensearch.client.opensearch.core.SearchRequest; +import org.opensearch.client.opensearch.core.SearchResponse; +import org.opensearch.client.opensearch.indices.SegmentSortOrder; + +public abstract class AbstractSearchRequestIT extends OpenSearchJavaClientTestCase { + + @Test + public void shouldReturnSearcheResults() throws Exception { + final String index = "searches_request"; + assertThat( + javaClient().indices() + .create( + 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))) + ) + .acknowledged(), + equalTo(true) + ); + + createTestDocuments(index); + javaClient().indices().refresh(); + + final Query query = Query.of( + q -> q.bool( + builder -> builder.filter(filter -> filter.term(TermQuery.of(term -> term.field("size").value(FieldValue.of("huge"))))) + ) + ); + + final SearchRequest request = SearchRequest.of( + r -> r.index(index) + .sort(s -> s.field(f -> f.field("name").order(SortOrder.Asc))) + .fields(f -> f.field("name")) + .query(query) + .source(s -> s.fetch(true)) + ); + + final SearchResponse response = javaClient().search(request, ShopItem.class); + assertThat(response.hits().hits(), hasSize(2)); + + assertThat(response.hits().hits().get(0).fields().get("name").to(String[].class), arrayContaining("hummer")); + assertThat(response.hits().hits().get(1).fields().get("name").to(String[].class), arrayContaining("jammer")); + } + + private void createTestDocuments(String index) throws IOException { + javaClient().create(_1 -> _1.index(index).id("1").document(createItem("hummer", "huge", "yes", 2))); + javaClient().create(_1 -> _1.index(index).id("2").document(createItem("jammer", "huge", "yes", 1))); + javaClient().create(_1 -> _1.index(index).id("3").document(createItem("hammer", "large", "yes", 3))); + javaClient().create(_1 -> _1.index(index).id("4").document(createItem("drill", "large", "yes", 3))); + javaClient().create(_1 -> _1.index(index).id("5").document(createItem("jack", "medium", "yes", 2))); + javaClient().create(_1 -> _1.index(index).id("6").document(createItem("wrench", "medium", "no", 3))); + javaClient().create(_1 -> _1.index(index).id("7").document(createItem("screws", "small", "no", 1))); + javaClient().create(_1 -> _1.index(index).id("8").document(createItem("nuts", "small", "no", 2))); + } + + private ShopItem createItem(String name, String size, String company, int quantity) { + return new ShopItem(name, size, company, quantity); + } + + public static class ShopItem { + private String name; + private String size; + private String company; + private int quantity; + + public ShopItem() {} + + public ShopItem(String name, String size, String company, int quantity) { + this.name = name; + this.size = size; + this.company = company; + this.quantity = quantity; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getSize() { + return size; + } + + public void setSize(String size) { + this.size = size; + } + + public String getCompany() { + return company; + } + + public void setCompany(String company) { + this.company = company; + } + + public int getQuantity() { + return quantity; + } + + public void setQuantity(int quantity) { + this.quantity = quantity; + } + } +} diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/httpclient5/SearchRequestIT.java b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/httpclient5/SearchRequestIT.java new file mode 100644 index 0000000000..322b877f63 --- /dev/null +++ b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/httpclient5/SearchRequestIT.java @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.client.opensearch.integTest.httpclient5; + +import org.opensearch.client.opensearch.integTest.AbstractSearchRequestIT; + +public class SearchRequestIT extends AbstractSearchRequestIT implements HttpClient5TransportSupport {} diff --git a/java-client/src/test/java/org/opensearch/client/opensearch/integTest/restclient/SearchRequestIT.java b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/restclient/SearchRequestIT.java new file mode 100644 index 0000000000..fda4d1c9d5 --- /dev/null +++ b/java-client/src/test/java/org/opensearch/client/opensearch/integTest/restclient/SearchRequestIT.java @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * + * The OpenSearch Contributors require contributions made to + * this file be licensed under the Apache-2.0 license or a + * compatible open source license. + */ + +package org.opensearch.client.opensearch.integTest.restclient; + +import java.io.IOException; +import org.apache.hc.core5.http.HttpHost; +import org.opensearch.client.json.jackson.JacksonJsonpMapper; +import org.opensearch.client.opensearch.integTest.AbstractSearchRequestIT; +import org.opensearch.client.transport.OpenSearchTransport; +import org.opensearch.client.transport.rest_client.RestClientTransport; +import org.opensearch.common.settings.Settings; + +public class SearchRequestIT extends AbstractSearchRequestIT { + @Override + public OpenSearchTransport buildTransport(Settings settings, HttpHost[] hosts) throws IOException { + return new RestClientTransport(buildClient(settings, hosts), new JacksonJsonpMapper()); + } +}