diff --git a/docs/reference/getting-started.md b/docs/reference/getting-started.md
index 4559b6f2e..cce1876f8 100644
--- a/docs/reference/getting-started.md
+++ b/docs/reference/getting-started.md
@@ -22,7 +22,6 @@ This page guides you through the installation process of the Java client, shows
```groovy
dependencies {
implementation 'co.elastic.clients:elasticsearch-java:9.0.0-beta1'
- implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0'
}
```
@@ -41,12 +40,6 @@ In the `pom.xml` of your project, add the following repository definition and de
9.0.0-beta1
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.17.0
-
-
```
diff --git a/docs/reference/installation.md b/docs/reference/installation.md
index b174e9395..dacc9767d 100644
--- a/docs/reference/installation.md
+++ b/docs/reference/installation.md
@@ -18,7 +18,6 @@ Releases are hosted on [Maven Central](https://search.maven.org/search?q=g:co.el
```groovy
dependencies {
implementation 'co.elastic.clients:elasticsearch-java:9.0.0-beta1'
- implementation 'com.fasterxml.jackson.core:jackson-databind:2.17.0'
}
```
@@ -37,12 +36,6 @@ In the `pom.xml` of your project, add the following repository definition and de
9.0.0-beta1
-
- com.fasterxml.jackson.core
- jackson-databind
- 2.17.0
-
-
```
diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts
index 00eea5d26..828f4de0b 100644
--- a/java-client/build.gradle.kts
+++ b/java-client/build.gradle.kts
@@ -160,6 +160,9 @@ publishing {
}
withXml {
+ // Note: org.elasticsearch.client is now an optional dependency, so the below is no more useful.
+ // It's kept in case it ever comes back as a required dependency.
+
// Set the version of dependencies of the org.elasticsearch.client group to the one that we are building.
// Since the unified release process releases everything at once, this ensures all published artifacts depend
// on the exact same version. This assumes of course that the binary API and the behavior of these dependencies
@@ -169,21 +172,14 @@ publishing {
.compile("/project/dependencies/dependency[groupId/text() = 'org.elasticsearch.client']")
val versionSelector = xPathFactory.newXPath().compile("version")
- var foundVersion = false;
-
val deps = depSelector.evaluate(asElement().ownerDocument, javax.xml.xpath.XPathConstants.NODESET)
as org.w3c.dom.NodeList
for (i in 0 until deps.length) {
val dep = deps.item(i)
val version = versionSelector.evaluate(dep, javax.xml.xpath.XPathConstants.NODE) as org.w3c.dom.Element
- foundVersion = true;
version.textContent = project.version.toString()
}
-
- if (!foundVersion) {
- throw GradleException("Could not find a 'org.elasticsearch.client' to update dependency version in the POM.")
- }
}
}
}
@@ -198,15 +194,16 @@ signing {
}
dependencies {
- // Compile and test with the last 7.x version to make sure transition scenarios where
- // the Java API client coexists with a 7.x HLRC work fine
+ // Compile and test with the last 8.x version to make sure transition scenarios where
+ // the Java API client coexists with a 8.x HLRC work fine
val elasticsearchVersion = "8.17.0"
- val jacksonVersion = "2.17.0"
+ val jacksonVersion = "2.18.3"
val openTelemetryVersion = "1.29.0"
// Apache 2.0
// https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-low.html
- api("org.elasticsearch.client", "elasticsearch-rest-client", elasticsearchVersion)
+ compileOnly("org.elasticsearch.client", "elasticsearch-rest-client", elasticsearchVersion)
+ testImplementation("org.elasticsearch.client", "elasticsearch-rest-client", elasticsearchVersion)
api("org.apache.httpcomponents.client5","httpclient5","5.4")
@@ -216,12 +213,12 @@ dependencies {
// EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// https://github.com/eclipse-ee4j/jsonp
- api("jakarta.json:jakarta.json-api:2.0.1")
+ api("jakarta.json:jakarta.json-api:2.1.3")
// Needed even if using Jackson to have an implementation of the Jsonp object model
// EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// https://github.com/eclipse-ee4j/parsson
- api("org.eclipse.parsson:parsson:1.0.5")
+ api("org.eclipse.parsson:parsson:1.1.7")
// OpenTelemetry API for native instrumentation of the client.
// Apache 2.0
@@ -229,25 +226,21 @@ dependencies {
implementation("io.opentelemetry", "opentelemetry-api", openTelemetryVersion)
// Use it once it's stable (see Instrumentation.java). Limited to tests for now.
testImplementation("io.opentelemetry", "opentelemetry-semconv", "$openTelemetryVersion-alpha")
+ testImplementation("io.opentelemetry", "opentelemetry-sdk", openTelemetryVersion)
// EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
// https://github.com/eclipse-ee4j/jsonb-api
- compileOnly("jakarta.json.bind", "jakarta.json.bind-api", "2.0.0")
- testImplementation("jakarta.json.bind", "jakarta.json.bind-api", "2.0.0")
+ compileOnly("jakarta.json.bind", "jakarta.json.bind-api", "3.0.1")
+ testImplementation("jakarta.json.bind", "jakarta.json.bind-api", "3.0.1")
// Apache 2.0
// https://github.com/FasterXML/jackson
- compileOnly("com.fasterxml.jackson.core", "jackson-core", jacksonVersion)
- compileOnly("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion)
- testImplementation("com.fasterxml.jackson.core", "jackson-core", jacksonVersion)
- testImplementation("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion)
+ implementation("com.fasterxml.jackson.core", "jackson-core", jacksonVersion)
+ implementation("com.fasterxml.jackson.core", "jackson-databind", jacksonVersion)
// EPL-2.0 OR BSD-3-Clause
// https://eclipse-ee4j.github.io/yasson/
- testImplementation("org.eclipse", "yasson", "2.0.4") {
- // Exclude Glassfish as we use Parsson (basically Glassfish renamed in the Jakarta namespace).
- exclude(group = "org.glassfish", module = "jakarta.json")
- }
+ testImplementation("org.eclipse", "yasson", "3.0.4")
// Apache-2.0
testImplementation("commons-io:commons-io:2.17.0")
@@ -268,8 +261,6 @@ dependencies {
// updating transitive dependency from testcontainers
testImplementation("org.apache.commons","commons-compress","1.26.1")
- testImplementation("io.opentelemetry", "opentelemetry-sdk", openTelemetryVersion)
-
// Apache-2.0
// https://github.com/awaitility/awaitility
testImplementation("org.awaitility", "awaitility", "4.2.0")
@@ -324,10 +315,15 @@ class SpdxReporter(val dest: File) : ReportRenderer {
val depName = dep.group + ":" + dep.name
val info = LicenseDataCollector.multiModuleLicenseInfo(dep)
- val depUrl = if (depName.startsWith("org.apache.httpcomponents")) {
- "https://hc.apache.org/"
- } else {
- info.moduleUrls.first()
+ val depUrl = when(dep.group) {
+ "org.apache.httpcomponents.client5" -> "https://hc.apache.org/"
+ "org.apache.httpcomponents.core5" -> "https://hc.apache.org/"
+ "com.fasterxml.jackson" -> "https://github.com/FasterXML/jackson"
+ else -> if (info.moduleUrls.isEmpty()) {
+ throw RuntimeException("No URL found for module '$depName'")
+ } else {
+ info.moduleUrls.first()
+ }
}
val licenseIds = info.licenses.mapNotNull { license ->
diff --git a/java-client/src/main/java/co/elastic/clients/json/JsonpUtils.java b/java-client/src/main/java/co/elastic/clients/json/JsonpUtils.java
index 74f888d04..bb628a5c7 100644
--- a/java-client/src/main/java/co/elastic/clients/json/JsonpUtils.java
+++ b/java-client/src/main/java/co/elastic/clients/json/JsonpUtils.java
@@ -19,6 +19,7 @@
package co.elastic.clients.json;
+import co.elastic.clients.json.jackson.JacksonJsonProvider;
import co.elastic.clients.util.AllowForbiddenApis;
import jakarta.json.JsonException;
import jakarta.json.JsonObject;
@@ -43,6 +44,7 @@
public class JsonpUtils {
private static JsonProvider systemJsonProvider = null;
+ private static JsonProvider defaultJsonProvider = null;
/**
* Get a JsonProvider
instance. This method first calls the standard `JsonProvider.provider()` that is based on
@@ -50,16 +52,48 @@ public class JsonpUtils {
* value is cached for subsequent calls.
*/
public static JsonProvider provider() {
- JsonProvider result = systemJsonProvider;
+ JsonProvider result = defaultJsonProvider;
if (result == null) {
result = findProvider();
+ defaultJsonProvider = result;
+ }
+ return result;
+ }
+
+ /**
+ * Sets the JsonProvider
that will be returned by {@link JsonProvider}.
+ */
+ public static void setProvider(JsonProvider provider) {
+ defaultJsonProvider = provider;
+ }
+
+ static JsonProvider findProvider() {
+ try {
+ // Default to Jackson
+ Class.forName("com.fasterxml.jackson.databind.ObjectMapper");
+ return new JacksonJsonProvider();
+ } catch (ClassNotFoundException e) {
+ return findSystemProvider();
+ }
+ }
+
+ /**
+ * Get the system's JsonProvider
instance return by {@code ServiceLoader}. First calls the standard
+ * `JsonProvider.provider()` that is based on the current thread's context classloader, and in case of failure tries to
+ * find a provider in other classloaders. The value is cached for subsequent calls.
+ */
+ public static JsonProvider systemProvider() {
+ JsonProvider result = systemJsonProvider;
+ if (result == null) {
+ result = findSystemProvider();
systemJsonProvider = result;
}
return result;
}
@AllowForbiddenApis("Implementation of the JsonProvider lookup")
- static JsonProvider findProvider() {
+ static JsonProvider findSystemProvider() {
+
RuntimeException exception;
try {
return JsonProvider.provider();
diff --git a/java-client/src/main/java/co/elastic/clients/json/SimpleJsonpMapper.java b/java-client/src/main/java/co/elastic/clients/json/SimpleJsonpMapper.java
index 67a37428e..4d6ccf874 100644
--- a/java-client/src/main/java/co/elastic/clients/json/SimpleJsonpMapper.java
+++ b/java-client/src/main/java/co/elastic/clients/json/SimpleJsonpMapper.java
@@ -90,7 +90,7 @@ public boolean ignoreUnknownFields() {
@Override
public JsonProvider jsonProvider() {
- return JsonpUtils.provider();
+ return JsonpUtils.systemProvider();
}
@Override
diff --git a/java-client/src/main/java/co/elastic/clients/json/jackson/JacksonJsonProvider.java b/java-client/src/main/java/co/elastic/clients/json/jackson/JacksonJsonProvider.java
index 37590afb6..d42159b14 100644
--- a/java-client/src/main/java/co/elastic/clients/json/jackson/JacksonJsonProvider.java
+++ b/java-client/src/main/java/co/elastic/clients/json/jackson/JacksonJsonProvider.java
@@ -133,7 +133,7 @@ public JsonParser createParser(InputStream in, Charset charset) {
*/
@Override
public JsonParser createParser(JsonObject obj) {
- return JsonpUtils.provider().createParserFactory(null).createParser(obj);
+ return JsonpUtils.systemProvider().createParserFactory(null).createParser(obj);
}
/**
@@ -141,7 +141,7 @@ public JsonParser createParser(JsonObject obj) {
*/
@Override
public JsonParser createParser(JsonArray array) {
- return JsonpUtils.provider().createParserFactory(null).createParser(array);
+ return JsonpUtils.systemProvider().createParserFactory(null).createParser(array);
}
/**
diff --git a/java-client/src/main/java/co/elastic/clients/json/jackson/JsonValueParser.java b/java-client/src/main/java/co/elastic/clients/json/jackson/JsonValueParser.java
index 51cbd2099..6f9572388 100644
--- a/java-client/src/main/java/co/elastic/clients/json/jackson/JsonValueParser.java
+++ b/java-client/src/main/java/co/elastic/clients/json/jackson/JsonValueParser.java
@@ -40,11 +40,11 @@
* object (e.g. START_OBJECT, VALUE_NUMBER, etc).
*/
class JsonValueParser {
- private final JsonProvider provider = JsonpUtils.provider();
+ private final JsonProvider systemProvider = JsonpUtils.systemProvider();
public JsonObject parseObject(JsonParser parser) throws IOException {
- JsonObjectBuilder ob = provider.createObjectBuilder();
+ JsonObjectBuilder ob = systemProvider.createObjectBuilder();
JsonToken token;
while((token = parser.nextToken()) != JsonToken.END_OBJECT) {
@@ -59,7 +59,7 @@ public JsonObject parseObject(JsonParser parser) throws IOException {
}
public JsonArray parseArray(JsonParser parser) throws IOException {
- JsonArrayBuilder ab = provider.createArrayBuilder();
+ JsonArrayBuilder ab = systemProvider.createArrayBuilder();
while(parser.nextToken() != JsonToken.END_ARRAY) {
ab.add(parseValue(parser));
@@ -86,23 +86,23 @@ public JsonValue parseValue(JsonParser parser) throws IOException {
return JsonValue.NULL;
case VALUE_STRING:
- return provider.createValue(parser.getText());
+ return systemProvider.createValue(parser.getText());
case VALUE_NUMBER_FLOAT:
case VALUE_NUMBER_INT:
switch(parser.getNumberType()) {
case INT:
- return provider.createValue(parser.getIntValue());
+ return systemProvider.createValue(parser.getIntValue());
case LONG:
- return provider.createValue(parser.getLongValue());
+ return systemProvider.createValue(parser.getLongValue());
case FLOAT:
case DOUBLE:
// Use double also for floats, as JSON-P has no support for float
return new DoubleNumber(parser.getDoubleValue());
case BIG_DECIMAL:
- return provider.createValue(parser.getDecimalValue());
+ return systemProvider.createValue(parser.getDecimalValue());
case BIG_INTEGER:
- return provider.createValue(parser.getBigIntegerValue());
+ return systemProvider.createValue(parser.getBigIntegerValue());
}
default:
diff --git a/java-client/src/main/java/co/elastic/clients/json/jsonb/JsonbJsonpMapper.java b/java-client/src/main/java/co/elastic/clients/json/jsonb/JsonbJsonpMapper.java
index c936f92f4..6bb15a409 100644
--- a/java-client/src/main/java/co/elastic/clients/json/jsonb/JsonbJsonpMapper.java
+++ b/java-client/src/main/java/co/elastic/clients/json/jsonb/JsonbJsonpMapper.java
@@ -52,7 +52,8 @@ public JsonbJsonpMapper(JsonProvider jsonProvider, JsonbProvider jsonbProvider)
}
public JsonbJsonpMapper() {
- this(JsonpUtils.provider(), JsonbProvider.provider());
+ // Use a native JSON-P/JSON-B implementations.
+ this(JsonpUtils.systemProvider(), JsonbProvider.provider());
}
@Override
diff --git a/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java b/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java
index a7f9b7a75..0d7187394 100644
--- a/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java
+++ b/java-client/src/test/java/co/elastic/clients/json/JsonpUtilsTest.java
@@ -20,13 +20,13 @@
package co.elastic.clients.json;
import co.elastic.clients.elasticsearch.core.search.Hit;
+import co.elastic.clients.json.jackson.JacksonJsonProvider;
import co.elastic.clients.testkit.ModelTestCase;
import co.elastic.clients.elasticsearch.security.IndexPrivilege;
import co.elastic.clients.elasticsearch.security.IndicesPrivileges;
import co.elastic.clients.elasticsearch.security.RoleTemplateScript;
import co.elastic.clients.elasticsearch.security.UserIndicesPrivileges;
import co.elastic.clients.util.AllowForbiddenApis;
-import jakarta.json.JsonException;
import jakarta.json.spi.JsonProvider;
import jakarta.json.stream.JsonGenerator;
import jakarta.json.stream.JsonParser;
@@ -58,13 +58,7 @@ public Enumeration getResources(String name) {
ClassLoader savedLoader = Thread.currentThread().getContextClassLoader();
try {
Thread.currentThread().setContextClassLoader(emptyLoader);
-
- assertThrows(JsonException.class, () -> {
- assertNotNull(JsonProvider.provider());
- });
-
assertNotNull(JsonpUtils.provider());
-
} finally {
Thread.currentThread().setContextClassLoader(savedLoader);
}
@@ -91,6 +85,15 @@ public void testObjectToString() {
assertEquals("Hit: {\"_index\":\"idx\",\"_id\":\"id1\",\"_source\":\"Some user data\"}", hit.toString());
}
+ @Test
+ public void testDefaultProvider() {
+ // Provider defaults to Jackson
+ assertTrue(JsonpUtils.provider() instanceof JacksonJsonProvider);
+
+ // System provider uses service lookup
+ assertFalse(JsonpUtils.systemProvider() instanceof JacksonJsonProvider);
+ }
+
private static class SomeUserData {
@Override
public String toString() {
diff --git a/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java b/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java
index 7d6cdbbb2..f935c9d82 100644
--- a/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java
+++ b/java-client/src/test/java/co/elastic/clients/testkit/ModelTestCase.java
@@ -50,7 +50,7 @@ protected enum JsonImpl { Jsonb, Jackson, Simple };
protected final JsonpMapper mapper;
private static JsonImpl chooseJsonImpl(EnumSet jsonImplCandidates, int rand) {
- // Converting an EnumSet to an array always uses the same order.
+ // Converting an EnumSet an array always uses the same order.
return jsonImplCandidates.toArray(new JsonImpl[jsonImplCandidates.size()])[rand % jsonImplCandidates.size()];
}