From 7cd041ba7dcd61ec4d21809655a1d8025c222418 Mon Sep 17 00:00:00 2001 From: Rene Cordier Date: Wed, 9 Jul 2025 15:48:00 +0700 Subject: [PATCH] [UPDATE] Upgrading opensearch java client to v3 --- backends-common/opensearch/pom.xml | 14 +++- .../backends/opensearch/ClientProvider.java | 74 ++++++++++++------- .../opensearch/IndexCreationFactory.java | 4 +- .../opensearch/OpenSearchHealthCheckTest.java | 4 +- .../org/apache/james/util/docker/Images.java | 2 +- 5 files changed, 63 insertions(+), 35 deletions(-) diff --git a/backends-common/opensearch/pom.xml b/backends-common/opensearch/pom.xml index d693072e666..6ad41c82a9d 100644 --- a/backends-common/opensearch/pom.xml +++ b/backends-common/opensearch/pom.xml @@ -75,6 +75,16 @@ org.apache.commons commons-configuration2 + + org.apache.httpcomponents.client5 + httpclient5 + 5.5 + + + org.apache.httpcomponents.core5 + httpcore5 + 5.3.4 + org.apache.logging.log4j log4j-to-slf4j @@ -87,12 +97,12 @@ org.opensearch.client opensearch-java - 2.25.0 + 3.1.0 org.opensearch.client opensearch-rest-client - 2.19.2 + 3.1.0 org.slf4j diff --git a/backends-common/opensearch/src/main/java/org/apache/james/backends/opensearch/ClientProvider.java b/backends-common/opensearch/src/main/java/org/apache/james/backends/opensearch/ClientProvider.java index bc87d19f36d..aca9f95ec42 100644 --- a/backends-common/opensearch/src/main/java/org/apache/james/backends/opensearch/ClientProvider.java +++ b/backends-common/opensearch/src/main/java/org/apache/james/backends/opensearch/ClientProvider.java @@ -35,16 +35,21 @@ import org.apache.commons.lang3.NotImplementedException; import org.apache.commons.lang3.time.DurationFormatUtils; -import org.apache.http.HttpHost; -import org.apache.http.auth.AuthScope; -import org.apache.http.auth.UsernamePasswordCredentials; -import org.apache.http.client.CredentialsProvider; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.conn.ssl.DefaultHostnameVerifier; -import org.apache.http.impl.client.BasicCredentialsProvider; -import org.apache.http.impl.nio.client.HttpAsyncClientBuilder; -import org.apache.http.ssl.SSLContextBuilder; -import org.apache.http.ssl.TrustStrategy; +import org.apache.hc.client5.http.auth.AuthScope; +import org.apache.hc.client5.http.auth.CredentialsStore; +import org.apache.hc.client5.http.auth.UsernamePasswordCredentials; +import org.apache.hc.client5.http.config.RequestConfig; +import org.apache.hc.client5.http.impl.async.HttpAsyncClientBuilder; +import org.apache.hc.client5.http.impl.auth.BasicCredentialsProvider; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManager; +import org.apache.hc.client5.http.impl.nio.PoolingAsyncClientConnectionManagerBuilder; +import org.apache.hc.client5.http.ssl.ClientTlsStrategyBuilder; +import org.apache.hc.client5.http.ssl.DefaultHostnameVerifier; +import org.apache.hc.core5.http.HttpHost; +import org.apache.hc.core5.http.nio.ssl.TlsStrategy; +import org.apache.hc.core5.ssl.SSLContextBuilder; +import org.apache.hc.core5.ssl.TrustStrategy; +import org.apache.hc.core5.util.Timeout; import org.apache.james.util.concurrent.NamedThreadFactory; import org.opensearch.client.RestClient; import org.opensearch.client.json.jackson.JacksonJsonpMapper; @@ -60,7 +65,7 @@ public class ClientProvider implements Provider { private static class HttpAsyncClientConfigurer { - + private static final AuthScope ANY = new AuthScope(null, null, -1, null, null); private static final TrustStrategy TRUST_ALL = (x509Certificates, authType) -> true; private static final HostnameVerifier ACCEPT_ANY_HOSTNAME = (hostname, sslSession) -> true; @@ -75,9 +80,6 @@ private HttpAsyncClientBuilder configure(HttpAsyncClientBuilder builder) { configureHostScheme(builder); configureTimeout(builder); - configuration.getMaxConnections().ifPresent(builder::setMaxConnTotal); - configuration.getMaxConnectionsPerHost().ifPresent(builder::setMaxConnPerRoute); - builder.setThreadFactory(NamedThreadFactory.withName("OpenSearch-driver")); return builder; @@ -99,19 +101,35 @@ private void configureHostScheme(HttpAsyncClientBuilder builder) { } private void configureSSLOptions(HttpAsyncClientBuilder builder) { - try { - builder - .setSSLContext(sslContext()) - .setSSLHostnameVerifier(hostnameVerifier()); - } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | CertificateException | IOException e) { - throw new RuntimeException("Cannot set SSL options to the builder", e); - } + builder.setConnectionManager(connectionManager()); } private void configureTimeout(HttpAsyncClientBuilder builder) { builder.setDefaultRequestConfig(requestConfig()); } + private PoolingAsyncClientConnectionManager connectionManager() { + PoolingAsyncClientConnectionManagerBuilder builder = PoolingAsyncClientConnectionManagerBuilder + .create() + .setTlsStrategy(tlsStrategy()); + + configuration.getMaxConnections().ifPresent(builder::setMaxConnTotal); + configuration.getMaxConnectionsPerHost().ifPresent(builder::setMaxConnPerRoute); + + return builder.build(); + } + + private TlsStrategy tlsStrategy() { + try { + return ClientTlsStrategyBuilder.create() + .setSslContext(sslContext()) + .setHostnameVerifier(hostnameVerifier()) + .buildAsync(); + } catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | CertificateException | IOException e) { + throw new RuntimeException("Cannot set SSL options to the builder", e); + } + } + private SSLContext sslContext() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException, CertificateException, IOException { @@ -152,9 +170,9 @@ private HostnameVerifier hostnameVerifier() { private RequestConfig requestConfig() { return RequestConfig.custom() - .setConnectTimeout(Math.toIntExact(configuration.getRequestTimeout().toMillis())) - .setConnectionRequestTimeout(Math.toIntExact(configuration.getRequestTimeout().toMillis())) - .setSocketTimeout(Math.toIntExact(configuration.getRequestTimeout().toMillis())) + .setConnectTimeout(Timeout.of(configuration.getRequestTimeout())) + .setConnectionRequestTimeout(Timeout.of(configuration.getRequestTimeout())) + .setResponseTimeout(Timeout.of(configuration.getRequestTimeout())) .build(); } @@ -172,9 +190,9 @@ private SSLContextBuilder applyTrustStore(SSLContextBuilder sslContextBuilder) t private void configureAuthentication(HttpAsyncClientBuilder builder) { configuration.getCredential() .ifPresent(credential -> { - CredentialsProvider credentialsProvider = new BasicCredentialsProvider(); - credentialsProvider.setCredentials(AuthScope.ANY, - new UsernamePasswordCredentials(credential.getUsername(), String.valueOf(credential.getPassword()))); + CredentialsStore credentialsProvider = new BasicCredentialsProvider(); + credentialsProvider.setCredentials(ANY, + new UsernamePasswordCredentials(credential.getUsername(), credential.getPassword())); builder.setDefaultCredentialsProvider(credentialsProvider); }); } @@ -225,7 +243,7 @@ private OpenSearchAsyncClient connectToCluster() { private HttpHost[] hostsToHttpHosts() { return configuration.getHosts().stream() - .map(host -> new HttpHost(host.getHostName(), host.getPort(), configuration.getHostScheme().name())) + .map(host -> new HttpHost(configuration.getHostScheme().name(), host.getHostName(), host.getPort())) .toArray(HttpHost[]::new); } diff --git a/backends-common/opensearch/src/main/java/org/apache/james/backends/opensearch/IndexCreationFactory.java b/backends-common/opensearch/src/main/java/org/apache/james/backends/opensearch/IndexCreationFactory.java index b2864f63e14..76b3d35fcbd 100644 --- a/backends-common/opensearch/src/main/java/org/apache/james/backends/opensearch/IndexCreationFactory.java +++ b/backends-common/opensearch/src/main/java/org/apache/james/backends/opensearch/IndexCreationFactory.java @@ -264,8 +264,8 @@ private boolean indexExists(ReactorOpenSearchClient client, IndexName indexName) private IndexSettings generateSetting() { return new IndexSettings.Builder() - .numberOfShards(Integer.toString(nbShards)) - .numberOfReplicas(Integer.toString(nbReplica)) + .numberOfShards(nbShards) + .numberOfReplicas(nbReplica) .analysis(new IndexSettingsAnalysis.Builder() .normalizer(CASE_INSENSITIVE, new Normalizer.Builder() .custom(generateNormalizer()) diff --git a/backends-common/opensearch/src/test/java/org/apache/james/backends/opensearch/OpenSearchHealthCheckTest.java b/backends-common/opensearch/src/test/java/org/apache/james/backends/opensearch/OpenSearchHealthCheckTest.java index 1e40074c7f1..c3c9875ad28 100644 --- a/backends-common/opensearch/src/test/java/org/apache/james/backends/opensearch/OpenSearchHealthCheckTest.java +++ b/backends-common/opensearch/src/test/java/org/apache/james/backends/opensearch/OpenSearchHealthCheckTest.java @@ -33,7 +33,7 @@ private static HealthResponse fakeHealthResponse(HealthStatus status) { .clusterName("fake-cluster") .activePrimaryShards(0) .activeShards(0) - .activeShardsPercentAsNumber("0") + .activeShardsPercentAsNumber(0) .delayedUnassignedShards(0) .initializingShards(0) .numberOfDataNodes(0) @@ -41,7 +41,7 @@ private static HealthResponse fakeHealthResponse(HealthStatus status) { .numberOfNodes(0) .numberOfPendingTasks(0) .relocatingShards(0) - .taskMaxWaitingInQueueMillis(String.valueOf(System.currentTimeMillis())) + .taskMaxWaitingInQueueMillis(System.currentTimeMillis()) .timedOut(false) .unassignedShards(0) .status(status) diff --git a/server/testing/src/main/java/org/apache/james/util/docker/Images.java b/server/testing/src/main/java/org/apache/james/util/docker/Images.java index 48c4a6dc527..349677eaf25 100644 --- a/server/testing/src/main/java/org/apache/james/util/docker/Images.java +++ b/server/testing/src/main/java/org/apache/james/util/docker/Images.java @@ -24,7 +24,7 @@ public interface Images { String RABBITMQ = "rabbitmq:4.1.1-management"; String ELASTICSEARCH_2 = "elasticsearch:2.4.6"; String ELASTICSEARCH_6 = "docker.elastic.co/elasticsearch/elasticsearch:6.3.2"; - String OPENSEARCH = "opensearchproject/opensearch:2.19.2"; + String OPENSEARCH = "opensearchproject/opensearch:3.1.0"; String TIKA = "apache/tika:3.2.0.0"; String MOCK_SMTP_SERVER = "linagora/mock-smtp-server:0.7"; String OPEN_LDAP = "osixia/openldap:1.5.0";