This is an automated email from the ASF dual-hosted git repository. dsmiley pushed a commit to branch branch_9x in repository https://gitbox.apache.org/repos/asf/solr.git
commit 9e5522127c93d1d8ac0fc54a7aa836e75b3eed98 Author: David Smiley <[email protected]> AuthorDate: Mon Sep 8 20:08:21 2025 -0400 SOLR-17884: SolrJ, minimize org.apache.http usage (#3602) SolrJ users not using deprecated SolrClients can safely exclude Apache HttpClient dependencies. * SolrJ Utils: Move org.apache.http usage to HttpClientUtil * SolrHttpConstants extracted from HttpClientUtil Did *not* bother updating deprecated classes that refer to HttpClientUtil; not necessary. (cherry picked from commit 9f6ef0acfebd9458cae8c5b1bc3ba0224ff26933) --- solr/CHANGES.txt | 3 + .../java/org/apache/solr/core/BlobRepository.java | 3 +- .../java/org/apache/solr/core/SolrXmlConfig.java | 10 +- .../java/org/apache/solr/handler/IndexFetcher.java | 8 +- .../handler/component/HttpShardHandlerFactory.java | 13 +-- .../solr/security/PKIAuthenticationPlugin.java | 5 - .../java/org/apache/solr/servlet/HttpSolrCall.java | 2 +- .../org/apache/solr/update/UpdateShardHandler.java | 13 +-- .../solr/update/UpdateShardHandlerConfig.java | 14 +-- .../apache/solr/cloud/RecoveryZkTestWithAuth.java | 4 +- .../solr/cloud/TestMiniSolrCloudClusterSSL.java | 8 +- .../solr/core/TestHttpSolrClientProvider.java | 4 +- .../solr/filestore/TestDistribFileStore.java | 9 +- .../handler/admin/api/ClusterPropsAPITest.java | 34 ++++-- .../solr/metrics/SolrMetricsIntegrationTest.java | 7 +- .../src/test/org/apache/solr/pkg/TestPackages.java | 7 +- .../solr/security/BasicAuthIntegrationTest.java | 4 +- .../solr/security/BasicAuthStandaloneTest.java | 2 +- .../apache/solr/security/MultiAuthPluginTest.java | 2 +- .../security/jwt/JWTAuthPluginIntegrationTest.java | 3 +- .../pages/major-changes-in-solr-9.adoc | 9 +- .../solr/client/solrj/io/SolrClientCache.java | 6 +- .../solrj/impl/ConcurrentUpdateSolrClient.java | 3 +- .../solr/client/solrj/impl/Http2SolrClient.java | 4 +- .../solrj/impl/HttpClientBuilderFactory.java | 1 + .../solr/client/solrj/impl/HttpClientUtil.java | 117 +++++++++++++-------- .../solr/client/solrj/impl/HttpSolrClient.java | 2 +- .../solrj/impl/HttpSolrClientBuilderBase.java | 4 +- .../PreemptiveBasicAuthClientBuilderFactory.java | 8 +- .../solr/client/solrj/impl/SolrHttpConstants.java | 62 +++++++++++ .../java/org/apache/solr/common/util/Utils.java | 70 ------------ .../client/solrj/SolrSchemalessExampleTest.java | 3 +- .../client/solrj/impl/Http2SolrClientTest.java | 6 +- .../apache/solr/cloud/SolrCloudAuthTestCase.java | 3 +- .../java/org/apache/solr/util/SSLTestConfig.java | 4 +- 35 files changed, 254 insertions(+), 203 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 7977e711944..ed1785841df 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -15,6 +15,9 @@ Improvements * SOLR-17893: Speed up Remote Proxy for high QPS, utilizing ClusterState caching. (Houston Putman) +* SOLR-17884: SolrJ users not using deprecated SolrClients can safely exclude Apache HttpClient dependencies. + (David Smiley) + Optimizations --------------------- (No changes) diff --git a/solr/core/src/java/org/apache/solr/core/BlobRepository.java b/solr/core/src/java/org/apache/solr/core/BlobRepository.java index 0251158a664..0dea58e0e23 100644 --- a/solr/core/src/java/org/apache/solr/core/BlobRepository.java +++ b/solr/core/src/java/org/apache/solr/core/BlobRepository.java @@ -39,6 +39,7 @@ import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; +import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.common.SolrException; import org.apache.solr.common.cloud.ClusterState; import org.apache.solr.common.cloud.DocCollection; @@ -227,7 +228,7 @@ public class BlobRepository { throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "could not load : " + key, e); } } finally { - Utils.consumeFully(entity); + HttpClientUtil.consumeFully(entity); } return b; } diff --git a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java index 5c480f90624..6bb5d6e8427 100644 --- a/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java +++ b/solr/core/src/java/org/apache/solr/core/SolrXmlConfig.java @@ -38,7 +38,7 @@ import java.util.function.Consumer; import java.util.regex.Pattern; import java.util.stream.Collectors; import javax.management.MBeanServer; -import org.apache.solr.client.solrj.impl.HttpClientUtil; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.cloud.ClusterSingleton; import org.apache.solr.cluster.placement.PlacementPluginFactory; import org.apache.solr.common.ConfigNode; @@ -459,10 +459,10 @@ public class SolrXmlConfig { boolean defined = false; - int maxUpdateConnections = HttpClientUtil.DEFAULT_MAXCONNECTIONS; - int maxUpdateConnectionsPerHost = HttpClientUtil.DEFAULT_MAXCONNECTIONSPERHOST; - int distributedSocketTimeout = HttpClientUtil.DEFAULT_SO_TIMEOUT; - int distributedConnectionTimeout = HttpClientUtil.DEFAULT_CONNECT_TIMEOUT; + int maxUpdateConnections = SolrHttpConstants.DEFAULT_MAXCONNECTIONS; + int maxUpdateConnectionsPerHost = SolrHttpConstants.DEFAULT_MAXCONNECTIONSPERHOST; + int distributedSocketTimeout = SolrHttpConstants.DEFAULT_SO_TIMEOUT; + int distributedConnectionTimeout = SolrHttpConstants.DEFAULT_CONNECT_TIMEOUT; String metricNameStrategy = UpdateShardHandlerConfig.DEFAULT_METRICNAMESTRATEGY; int maxRecoveryThreads = UpdateShardHandlerConfig.DEFAULT_MAXRECOVERYTHREADS; diff --git a/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java b/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java index cc18d79fe7c..80b391d8231 100644 --- a/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java +++ b/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java @@ -97,8 +97,8 @@ import org.apache.lucene.store.IndexOutput; import org.apache.solr.client.api.model.FileMetaData; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.Http2SolrClient; -import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.InputStreamResponseParser; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.cloud.CloudDescriptor; import org.apache.solr.cloud.ZkController; @@ -297,10 +297,10 @@ public class IndexFetcher { String compress = (String) initArgs.get(COMPRESSION); useInternalCompression = ReplicationHandler.INTERNAL.equals(compress); useExternalCompression = ReplicationHandler.EXTERNAL.equals(compress); - soTimeout = getParameter(initArgs, HttpClientUtil.PROP_SO_TIMEOUT, 120000, null); + soTimeout = getParameter(initArgs, SolrHttpConstants.PROP_SO_TIMEOUT, 120000, null); - String httpBasicAuthUser = (String) initArgs.get(HttpClientUtil.PROP_BASIC_AUTH_USER); - String httpBasicAuthPassword = (String) initArgs.get(HttpClientUtil.PROP_BASIC_AUTH_PASS); + String httpBasicAuthUser = (String) initArgs.get(SolrHttpConstants.PROP_BASIC_AUTH_USER); + String httpBasicAuthPassword = (String) initArgs.get(SolrHttpConstants.PROP_BASIC_AUTH_PASS); solrClient = createSolrClient(solrCore, httpBasicAuthUser, httpBasicAuthPassword, leaderBaseUrl); } diff --git a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java index 990e3312deb..bf050a328d8 100644 --- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java +++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java @@ -30,9 +30,9 @@ import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.impl.Http2SolrClient; -import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.LBHttp2SolrClient; import org.apache.solr.client.solrj.impl.LBSolrClient; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.routing.AffinityReplicaListTransformerFactory; import org.apache.solr.client.solrj.routing.ReplicaListTransformer; @@ -293,17 +293,18 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory int connectionTimeout = getParameter( args, - HttpClientUtil.PROP_CONNECTION_TIMEOUT, - HttpClientUtil.DEFAULT_CONNECT_TIMEOUT, + SolrHttpConstants.PROP_CONNECTION_TIMEOUT, + SolrHttpConstants.DEFAULT_CONNECT_TIMEOUT, sb); int maxConnectionsPerHost = getParameter( args, - HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, - HttpClientUtil.DEFAULT_MAXCONNECTIONSPERHOST, + SolrHttpConstants.PROP_MAX_CONNECTIONS_PER_HOST, + SolrHttpConstants.DEFAULT_MAXCONNECTIONSPERHOST, sb); int soTimeout = - getParameter(args, HttpClientUtil.PROP_SO_TIMEOUT, HttpClientUtil.DEFAULT_SO_TIMEOUT, sb); + getParameter( + args, SolrHttpConstants.PROP_SO_TIMEOUT, SolrHttpConstants.DEFAULT_SO_TIMEOUT, sb); this.defaultClient = new Http2SolrClient.Builder() diff --git a/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java b/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java index b6a2b97d374..fe5923eb751 100644 --- a/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java +++ b/solr/core/src/java/org/apache/solr/security/PKIAuthenticationPlugin.java @@ -40,7 +40,6 @@ import java.util.concurrent.TimeUnit; import javax.servlet.FilterChain; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.apache.http.HttpEntity; import org.apache.http.HttpException; import org.apache.http.HttpHeaders; import org.apache.http.HttpRequest; @@ -57,7 +56,6 @@ import org.apache.solr.common.util.ExecutorUtil; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.SuppressForbidden; -import org.apache.solr.common.util.Utils; import org.apache.solr.core.CoreContainer; import org.apache.solr.request.SolrRequestInfo; import org.apache.solr.util.CryptoKeys; @@ -384,7 +382,6 @@ public class PKIAuthenticationPlugin extends AuthenticationPlugin return null; } String url = cores.getZkController().getZkStateReader().getBaseUrlForNodeName(nodename); - HttpEntity entity = null; try { final var solrParams = new ModifiableSolrParams(); solrParams.add("wt", "json"); @@ -409,8 +406,6 @@ public class PKIAuthenticationPlugin extends AuthenticationPlugin } catch (Exception e) { log.error("Exception trying to get public key from: {}", url, e); return null; - } finally { - Utils.consumeFully(entity); } } diff --git a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java index 8f67b6acecd..9f4696e7740 100644 --- a/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java +++ b/solr/core/src/java/org/apache/solr/servlet/HttpSolrCall.java @@ -838,7 +838,7 @@ public class HttpSolrCall { + forwardCount, e)); } finally { - Utils.consumeFully(httpEntity); + HttpClientUtil.consumeFully(httpEntity); } } diff --git a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java index d3901eee182..ca6e65690c7 100644 --- a/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java +++ b/solr/core/src/java/org/apache/solr/update/UpdateShardHandler.java @@ -30,6 +30,7 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.solr.client.solrj.impl.Http2SolrClient; import org.apache.solr.client.solrj.impl.HttpClientUtil; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.common.SolrException; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.util.ExecutorUtil; @@ -87,8 +88,8 @@ public class UpdateShardHandler implements SolrInfoBean { private SolrMetricsContext solrMetricsContext; - private int socketTimeout = HttpClientUtil.DEFAULT_SO_TIMEOUT; - private int connectionTimeout = HttpClientUtil.DEFAULT_CONNECT_TIMEOUT; + private int socketTimeout = SolrHttpConstants.DEFAULT_SO_TIMEOUT; + private int connectionTimeout = SolrHttpConstants.DEFAULT_CONNECT_TIMEOUT; public UpdateShardHandler(UpdateShardHandlerConfig cfg) { defaultConnectionManager = @@ -98,15 +99,15 @@ public class UpdateShardHandler implements SolrInfoBean { if (cfg != null) { defaultConnectionManager.setMaxTotal(cfg.getMaxUpdateConnections()); defaultConnectionManager.setDefaultMaxPerRoute(cfg.getMaxUpdateConnectionsPerHost()); - clientParams.set(HttpClientUtil.PROP_SO_TIMEOUT, cfg.getDistributedSocketTimeout()); + clientParams.set(SolrHttpConstants.PROP_SO_TIMEOUT, cfg.getDistributedSocketTimeout()); clientParams.set( - HttpClientUtil.PROP_CONNECTION_TIMEOUT, cfg.getDistributedConnectionTimeout()); + SolrHttpConstants.PROP_CONNECTION_TIMEOUT, cfg.getDistributedConnectionTimeout()); // following is done only for logging complete configuration. // The maxConnections and maxConnectionsPerHost have already been specified on the connection // manager - clientParams.set(HttpClientUtil.PROP_MAX_CONNECTIONS, cfg.getMaxUpdateConnections()); + clientParams.set(SolrHttpConstants.PROP_MAX_CONNECTIONS, cfg.getMaxUpdateConnections()); clientParams.set( - HttpClientUtil.PROP_MAX_CONNECTIONS_PER_HOST, cfg.getMaxUpdateConnectionsPerHost()); + SolrHttpConstants.PROP_MAX_CONNECTIONS_PER_HOST, cfg.getMaxUpdateConnectionsPerHost()); socketTimeout = cfg.getDistributedSocketTimeout(); connectionTimeout = cfg.getDistributedConnectionTimeout(); } diff --git a/solr/core/src/java/org/apache/solr/update/UpdateShardHandlerConfig.java b/solr/core/src/java/org/apache/solr/update/UpdateShardHandlerConfig.java index 9913f86e397..46ffc19493b 100644 --- a/solr/core/src/java/org/apache/solr/update/UpdateShardHandlerConfig.java +++ b/solr/core/src/java/org/apache/solr/update/UpdateShardHandlerConfig.java @@ -16,7 +16,7 @@ */ package org.apache.solr.update; -import org.apache.solr.client.solrj.impl.HttpClientUtil; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; public class UpdateShardHandlerConfig { @@ -25,17 +25,17 @@ public class UpdateShardHandlerConfig { public static final UpdateShardHandlerConfig DEFAULT = new UpdateShardHandlerConfig( - HttpClientUtil.DEFAULT_MAXCONNECTIONS, - HttpClientUtil.DEFAULT_MAXCONNECTIONSPERHOST, - HttpClientUtil.DEFAULT_SO_TIMEOUT, - HttpClientUtil.DEFAULT_CONNECT_TIMEOUT, + SolrHttpConstants.DEFAULT_MAXCONNECTIONS, + SolrHttpConstants.DEFAULT_MAXCONNECTIONSPERHOST, + SolrHttpConstants.DEFAULT_SO_TIMEOUT, + SolrHttpConstants.DEFAULT_CONNECT_TIMEOUT, DEFAULT_METRICNAMESTRATEGY, DEFAULT_MAXRECOVERYTHREADS); public static final UpdateShardHandlerConfig TEST_DEFAULT = new UpdateShardHandlerConfig( - HttpClientUtil.DEFAULT_MAXCONNECTIONS, - HttpClientUtil.DEFAULT_MAXCONNECTIONSPERHOST, + SolrHttpConstants.DEFAULT_MAXCONNECTIONS, + SolrHttpConstants.DEFAULT_MAXCONNECTIONSPERHOST, 30000, 30000, UpdateShardHandlerConfig.DEFAULT_METRICNAMESTRATEGY, diff --git a/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTestWithAuth.java b/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTestWithAuth.java index 7edaa4090a2..fdd38d78973 100644 --- a/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTestWithAuth.java +++ b/solr/core/src/test/org/apache/solr/cloud/RecoveryZkTestWithAuth.java @@ -27,8 +27,8 @@ import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrResponse; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.CloudLegacySolrClient; -import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.QueryRequest; import org.apache.solr.client.solrj.request.UpdateRequest; @@ -65,7 +65,7 @@ public class RecoveryZkTestWithAuth extends SolrCloudTestCase { // for context) if (rarely()) { System.setProperty( - HttpClientUtil.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY, + SolrHttpConstants.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY, "org.apache.solr.client.solrj.impl.PreemptiveBasicAuthClientBuilderFactory"); System.setProperty("basicauth", user + ":" + pass); } diff --git a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java index 18ec44e430c..c1d76b93724 100644 --- a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java +++ b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java @@ -39,6 +39,7 @@ import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.impl.Http2SolrClient; import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.CoreAdminRequest; import org.apache.solr.common.cloud.ZkStateReader; @@ -81,7 +82,7 @@ public class TestMiniSolrCloudClusterSSL extends SolrTestCaseJ4 { @Rule public TestRule syspropRestore = - new TestRuleRestoreSystemProperties(HttpClientUtil.SYS_PROP_CHECK_PEER_NAME); + new TestRuleRestoreSystemProperties(SolrHttpConstants.SYS_PROP_CHECK_PEER_NAME); @Before public void before() { @@ -177,7 +178,8 @@ public class TestMiniSolrCloudClusterSSL extends SolrTestCaseJ4 { SSLContext.setDefault( sslConfig.isSSLMode() ? sslConfig.buildClientSSLContext() : DEFAULT_SSL_CONTEXT); System.setProperty( - HttpClientUtil.SYS_PROP_CHECK_PEER_NAME, Boolean.toString(sslConfig.getCheckPeerName())); + SolrHttpConstants.SYS_PROP_CHECK_PEER_NAME, + Boolean.toString(sslConfig.getCheckPeerName())); HttpClientUtil.resetHttpClientBuilder(); Http2SolrClient.resetSslContextFactory(); @@ -206,7 +208,7 @@ public class TestMiniSolrCloudClusterSSL extends SolrTestCaseJ4 { // now initialize a client that still uses the existing SSLContext/Provider, so it will accept // our existing certificate, but *does* care about validating the peer name - System.setProperty(HttpClientUtil.SYS_PROP_CHECK_PEER_NAME, "true"); + System.setProperty(SolrHttpConstants.SYS_PROP_CHECK_PEER_NAME, "true"); HttpClientUtil.resetHttpClientBuilder(); Http2SolrClient.resetSslContextFactory(); diff --git a/solr/core/src/test/org/apache/solr/core/TestHttpSolrClientProvider.java b/solr/core/src/test/org/apache/solr/core/TestHttpSolrClientProvider.java index 14b5a504634..3c3105923bf 100644 --- a/solr/core/src/test/org/apache/solr/core/TestHttpSolrClientProvider.java +++ b/solr/core/src/test/org/apache/solr/core/TestHttpSolrClientProvider.java @@ -22,7 +22,7 @@ import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import org.apache.solr.SolrTestCase; -import org.apache.solr.client.solrj.impl.HttpClientUtil; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.metrics.SolrMetricsContext; import org.apache.solr.update.UpdateShardHandlerConfig; import org.junit.Before; @@ -46,7 +46,7 @@ public class TestHttpSolrClientProvider extends SolrTestCase { try (var httpSolrClientProvider = new HttpSolrClientProvider(null, parentSolrMetricCtx); ) { assertEquals( httpSolrClientProvider.getSolrClient().getIdleTimeout(), - HttpClientUtil.DEFAULT_SO_TIMEOUT); + SolrHttpConstants.DEFAULT_SO_TIMEOUT); } } diff --git a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java index 26e36060789..e73244092c7 100644 --- a/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java +++ b/solr/core/src/test/org/apache/solr/filestore/TestDistribFileStore.java @@ -39,6 +39,7 @@ import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.BaseHttpSolrClient.RemoteExecutionException; +import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.request.V2Request; import org.apache.solr.client.solrj.response.SimpleSolrResponse; @@ -181,7 +182,7 @@ public class TestDistribFileStore extends SolrCloudTestCase { String path = j.getBaseURLV2() + "/cluster/files" + "/package/mypkg/v1.0/runtimelibs.jar"; HttpDelete del = new HttpDelete(path); try (HttpSolrClient cl = (HttpSolrClient) j.newClient()) { - Utils.executeHttpMethod(cl.getHttpClient(), path, Utils.JSONCONSUMER, del); + HttpClientUtil.executeHttpMethod(cl.getHttpClient(), path, Utils.JSONCONSUMER, del); } expected = Collections.singletonMap(":files:/package/mypkg/v1.0/runtimelibs.jar", null); checkAllNodesForFile(cluster, "/package/mypkg/v1.0/runtimelibs.jar", expected, false); @@ -204,7 +205,7 @@ public class TestDistribFileStore extends SolrCloudTestCase { if (verifyContent) { try (HttpSolrClient solrClient = (HttpSolrClient) jettySolrRunner.newClient()) { ByteBuffer buf = - Utils.executeGET( + HttpClientUtil.executeGET( solrClient.getHttpClient(), baseUrl + "/node/files" + path, Utils.newBytesConsumer(Integer.MAX_VALUE)); @@ -229,7 +230,7 @@ public class TestDistribFileStore extends SolrCloudTestCase { public NavigableObject call() throws Exception { try (HttpSolrClient solrClient = (HttpSolrClient) jetty.newClient()) { return (NavigableObject) - Utils.executeGET(solrClient.getHttpClient(), this.url, JAVABINCONSUMER); + HttpClientUtil.executeGET(solrClient.getHttpClient(), this.url, JAVABINCONSUMER); } } @@ -322,7 +323,7 @@ public class TestDistribFileStore extends SolrCloudTestCase { try (HttpSolrClient client = (HttpSolrClient) jetty.newClient()) { PackageUtils.uploadKey(bytes, path, Paths.get(jetty.getCoreContainer().getSolrHome())); String url = jetty.getBaseURLV2() + "/node/files" + path + "?sync=true"; - Object resp = Utils.executeGET(client.getHttpClient(), url, null); + Object resp = HttpClientUtil.executeGET(client.getHttpClient(), url, null); log.info("sync resp: {} was {}", url, resp); } checkAllNodesForFile( diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/ClusterPropsAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/ClusterPropsAPITest.java index f690dbc1498..a3cbbd2b6dc 100644 --- a/solr/core/src/test/org/apache/solr/handler/admin/api/ClusterPropsAPITest.java +++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ClusterPropsAPITest.java @@ -28,6 +28,7 @@ import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpPut; import org.apache.http.entity.StringEntity; +import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.cloud.SolrCloudTestCase; import org.apache.solr.common.util.Utils; @@ -91,7 +92,8 @@ public class ClusterPropsAPITest extends SolrCloudTestCase { // List Properties, confirm the test property does not exist // This ignores eventually existing other properties Object o = - Utils.executeGET(client.getHttpClient(), baseUrlV2ClusterProps, Utils.JSONCONSUMER); + HttpClientUtil.executeGET( + client.getHttpClient(), baseUrlV2ClusterProps, Utils.JSONCONSUMER); assertNotNull(o); @SuppressWarnings("unchecked") List<String> initProperties = (List<String>) getObjectByPath(o, true, "clusterProperties"); @@ -102,11 +104,15 @@ public class ClusterPropsAPITest extends SolrCloudTestCase { HttpPut httpPut = new HttpPut(path); httpPut.setHeader("Content-Type", "application/json"); httpPut.setEntity(new StringEntity("{\"value\":\"" + testClusterPropertyValue + "\"}")); - o = Utils.executeHttpMethod(client.getHttpClient(), path, Utils.JSONCONSUMER, httpPut); + o = + HttpClientUtil.executeHttpMethod( + client.getHttpClient(), path, Utils.JSONCONSUMER, httpPut); assertNotNull(o); // List Properties, this time there should be the just added property - o = Utils.executeGET(client.getHttpClient(), baseUrlV2ClusterProps, Utils.JSONCONSUMER); + o = + HttpClientUtil.executeGET( + client.getHttpClient(), baseUrlV2ClusterProps, Utils.JSONCONSUMER); assertNotNull(o); @SuppressWarnings("unchecked") List<String> updatedProperties = (List<String>) getObjectByPath(o, true, "clusterProperties"); @@ -114,7 +120,7 @@ public class ClusterPropsAPITest extends SolrCloudTestCase { // Fetch Cluster Property // Same path as used in the Create step above - o = Utils.executeGET(client.getHttpClient(), path, Utils.JSONCONSUMER); + o = HttpClientUtil.executeGET(client.getHttpClient(), path, Utils.JSONCONSUMER); assertNotNull(o); assertEquals(testClusterProperty, (String) getObjectByPath(o, true, "clusterProperty/name")); assertEquals( @@ -123,11 +129,15 @@ public class ClusterPropsAPITest extends SolrCloudTestCase { // Delete Cluster Property // Same path as used in the Create step above HttpDelete httpDelete = new HttpDelete(path); - o = Utils.executeHttpMethod(client.getHttpClient(), path, Utils.JSONCONSUMER, httpDelete); + o = + HttpClientUtil.executeHttpMethod( + client.getHttpClient(), path, Utils.JSONCONSUMER, httpDelete); assertNotNull(o); // List Properties, the test property should be gone - o = Utils.executeGET(client.getHttpClient(), baseUrlV2ClusterProps, Utils.JSONCONSUMER); + o = + HttpClientUtil.executeGET( + client.getHttpClient(), baseUrlV2ClusterProps, Utils.JSONCONSUMER); assertNotNull(o); @SuppressWarnings("unchecked") List<String> clearedProperties = (List<String>) getObjectByPath(o, true, "clusterProperties"); @@ -143,13 +153,13 @@ public class ClusterPropsAPITest extends SolrCloudTestCase { httpPut.setHeader("Content-Type", "application/json"); httpPut.setEntity(new StringEntity(testClusterPropertyBulkAndNestedValues)); Object o = - Utils.executeHttpMethod( + HttpClientUtil.executeHttpMethod( client.getHttpClient(), baseUrlV2ClusterProps, Utils.JSONCONSUMER, httpPut); assertNotNull(o); // Fetch Cluster Property checking the not-nested property set above String path = baseUrlV2ClusterProps + "/" + testClusterProperty; - o = Utils.executeGET(client.getHttpClient(), path, Utils.JSONCONSUMER); + o = HttpClientUtil.executeGET(client.getHttpClient(), path, Utils.JSONCONSUMER); assertNotNull(o); assertEquals(testClusterProperty, (String) getObjectByPath(o, true, "clusterProperty/name")); assertEquals( @@ -157,17 +167,19 @@ public class ClusterPropsAPITest extends SolrCloudTestCase { // Fetch Cluster Property checking the nested property set above path = baseUrlV2ClusterProps + "/" + "defaults"; - o = Utils.executeGET(client.getHttpClient(), path, Utils.JSONCONSUMER); + o = HttpClientUtil.executeGET(client.getHttpClient(), path, Utils.JSONCONSUMER); assertNotNull(o); assertEquals("defaults", (String) getObjectByPath(o, true, "clusterProperty/name")); assertEquals(4L, getObjectByPath(o, true, "clusterProperty/value/collection/numShards")); // Clean up to leave the state unchanged HttpDelete httpDelete = new HttpDelete(path); - Utils.executeHttpMethod(client.getHttpClient(), path, Utils.JSONCONSUMER, httpDelete); + HttpClientUtil.executeHttpMethod( + client.getHttpClient(), path, Utils.JSONCONSUMER, httpDelete); path = baseUrlV2ClusterProps + "/" + testClusterProperty; httpDelete = new HttpDelete(path); - Utils.executeHttpMethod(client.getHttpClient(), path, Utils.JSONCONSUMER, httpDelete); + HttpClientUtil.executeHttpMethod( + client.getHttpClient(), path, Utils.JSONCONSUMER, httpDelete); } } diff --git a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java index 06e9a59f54c..36cd1361563 100644 --- a/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/metrics/SolrMetricsIntegrationTest.java @@ -32,6 +32,7 @@ import org.apache.http.client.HttpClient; import org.apache.lucene.tests.util.TestUtil; import org.apache.solr.SolrTestCaseJ4; import org.apache.solr.client.solrj.SolrClient; +import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.cloud.MiniSolrCloudCluster; import org.apache.solr.common.util.Utils; @@ -240,7 +241,7 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 { Map<String, Object> zkMmetrics = (Map<String, Object>) Utils.getObjectByPath( - Utils.executeGET(httpClient, url, Utils.JSONCONSUMER), + HttpClientUtil.executeGET(httpClient, url, Utils.JSONCONSUMER), false, List.of("metrics", "solr.node:CONTAINER.zkClient")); @@ -261,7 +262,7 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 { for (String k : allKeys) { assertNotNull(zkMmetrics.get(k)); } - Utils.executeGET( + HttpClientUtil.executeGET( httpClient, j.getBaseURLV2() + "/cluster/zookeeper/children/live_nodes", Utils.JSONCONSUMER); @@ -269,7 +270,7 @@ public class SolrMetricsIntegrationTest extends SolrTestCaseJ4 { Map<String, Object> zkMmetricsNew = (Map<String, Object>) Utils.getObjectByPath( - Utils.executeGET(httpClient, url, Utils.JSONCONSUMER), + HttpClientUtil.executeGET(httpClient, url, Utils.JSONCONSUMER), false, List.of("metrics", "solr.node:CONTAINER.zkClient")); diff --git a/solr/core/src/test/org/apache/solr/pkg/TestPackages.java b/solr/core/src/test/org/apache/solr/pkg/TestPackages.java index b295b68f332..6b91f740f31 100644 --- a/solr/core/src/test/org/apache/solr/pkg/TestPackages.java +++ b/solr/core/src/test/org/apache/solr/pkg/TestPackages.java @@ -47,6 +47,7 @@ import org.apache.solr.client.solrj.SolrQuery; import org.apache.solr.client.solrj.SolrRequest; import org.apache.solr.client.solrj.SolrServerException; import org.apache.solr.client.solrj.impl.BaseHttpSolrClient; +import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.request.CollectionAdminRequest; import org.apache.solr.client.solrj.request.GenericSolrRequest; @@ -542,7 +543,8 @@ public class TestPackages extends SolrCloudTestCase { 10, () -> NavigableObject.wrap( - Utils.executeGET(client.getHttpClient(), jetty.getBaseUrl() + uri, parser)), + HttpClientUtil.executeGET( + client.getHttpClient(), jetty.getBaseUrl() + uri, parser)), expected); } } @@ -695,7 +697,8 @@ public class TestPackages extends SolrCloudTestCase { public NavigableObject call() throws Exception { try (HttpSolrClient solrClient = (HttpSolrClient) jetty.newClient()) { return (NavigableObject) - Utils.executeGET(solrClient.getHttpClient(), path, Utils.JAVABINCONSUMER); + HttpClientUtil.executeGET( + solrClient.getHttpClient(), path, Utils.JAVABINCONSUMER); } } }, diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java index 8a38bb0dfb6..2f785f7991f 100644 --- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java +++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java @@ -171,7 +171,7 @@ public class BasicAuthIntegrationTest extends SolrCloudAuthTestCase { verifySecurityStatus(cl, baseUrl + authcPrefix, "authentication.enabled", "true", 20); HttpResponse r = cl.execute(httpPost); int statusCode = r.getStatusLine().getStatusCode(); - Utils.consumeFully(r.getEntity()); + HttpClientUtil.consumeFully(r.getEntity()); assertEquals("proper_cred sent, but access denied", 200, statusCode); assertPkiAuthMetricsMinimums(0, 0, 0, 0, 0, 0); assertAuthMetricsMinimums(4, 1, 3, 0, 0, 0); @@ -457,7 +457,7 @@ public class BasicAuthIntegrationTest extends SolrCloudAuthTestCase { assertEquals( "Non-200 response code. Response was " + response, 200, r.getStatusLine().getStatusCode()); assertFalse("Response contained errors: " + response, response.contains("errorMessages")); - Utils.consumeFully(r.getEntity()); + HttpClientUtil.consumeFully(r.getEntity()); // HACK (continued)... final TimeOut timeout = new TimeOut(30, TimeUnit.SECONDS, TimeSource.NANO_TIME); diff --git a/solr/core/src/test/org/apache/solr/security/BasicAuthStandaloneTest.java b/solr/core/src/test/org/apache/solr/security/BasicAuthStandaloneTest.java index 6fa80de54ad..ad4a671d259 100644 --- a/solr/core/src/test/org/apache/solr/security/BasicAuthStandaloneTest.java +++ b/solr/core/src/test/org/apache/solr/security/BasicAuthStandaloneTest.java @@ -180,7 +180,7 @@ public class BasicAuthStandaloneTest extends SolrTestCaseJ4 { httpPost.addHeader("Content-Type", "application/json; charset=UTF-8"); HttpResponse r = cl.execute(httpPost); int statusCode = r.getStatusLine().getStatusCode(); - Utils.consumeFully(r.getEntity()); + HttpClientUtil.consumeFully(r.getEntity()); assertEquals("proper_cred sent, but access denied", expectStatusCode, statusCode); } diff --git a/solr/core/src/test/org/apache/solr/security/MultiAuthPluginTest.java b/solr/core/src/test/org/apache/solr/security/MultiAuthPluginTest.java index 7b6a821134d..07a58664264 100644 --- a/solr/core/src/test/org/apache/solr/security/MultiAuthPluginTest.java +++ b/solr/core/src/test/org/apache/solr/security/MultiAuthPluginTest.java @@ -274,7 +274,7 @@ public class MultiAuthPluginTest extends SolrTestCaseJ4 { HttpGet httpPost = new HttpGet(url); HttpResponse r = cl.execute(httpPost); int statusCode = r.getStatusLine().getStatusCode(); - Utils.consumeFully(r.getEntity()); + HttpClientUtil.consumeFully(r.getEntity()); return statusCode; } diff --git a/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginIntegrationTest.java b/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginIntegrationTest.java index e5e3223fdf2..b8e7bda0b46 100644 --- a/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginIntegrationTest.java +++ b/solr/modules/jwt-auth/src/test/org/apache/solr/security/jwt/JWTAuthPluginIntegrationTest.java @@ -62,7 +62,6 @@ import org.apache.solr.cloud.SolrCloudAuthTestCase; import org.apache.solr.common.SolrException; import org.apache.solr.common.util.Pair; import org.apache.solr.common.util.TimeSource; -import org.apache.solr.common.util.Utils; import org.apache.solr.embedded.JettySolrRunner; import org.apache.solr.util.CryptoKeys; import org.apache.solr.util.RTimer; @@ -530,7 +529,7 @@ public class JWTAuthPluginIntegrationTest extends SolrCloudAuthTestCase { assertEquals( "Non-200 response code. Response was " + response, 200, r.getStatusLine().getStatusCode()); assertFalse("Response contained errors: " + response, response.contains("errorMessages")); - Utils.consumeFully(r.getEntity()); + HttpClientUtil.consumeFully(r.getEntity()); // HACK (continued)... final TimeOut timeout = new TimeOut(30, TimeUnit.SECONDS, TimeSource.NANO_TIME); diff --git a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc index 9f0e1d127c8..e45eb0e0e57 100644 --- a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc +++ b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-9.adoc @@ -75,6 +75,13 @@ It is always strongly recommended that you fully reindex your documents after a In Solr 8, it was possible to add docValues to a schema without re-indexing via `UninvertDocValuesMergePolicy`, an advanced/expert utility. Due to changes in Lucene 9, that isn't possible any more. +== Solr 9.10 + +=== SolrJ + +SolrJ users not using SolrClients that use Apache HttpClient can safely exclude those dependencies. +SolrJ users not using SolrClients that use Jetty HttpClient can safely exclude those dependencies. + == Solr 9.9 === SolrJ @@ -255,7 +262,7 @@ Use `solr.useExitableDirectoryReader` to use the previous behavior. Please share your experience with Solr developers! The previous behavior should not be enabled if timeAllowed isn't used because unfortunately its performance tax is now imposed on all queries, even those without timeAllowed. -=== v2 API +=== v2 API * Solr's experimental "v2" API has seen a number of improvements in the 9.3 release. + It is now approaching parity with the functionality offered by Solr's v1 API. In particular 9.3 adds v2 "CRUD" endpoints for interacting with alias properties and collection snapshots. Several lower-level "replication" APIs now also offer v2 equivalents. diff --git a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java index 4cd1c627312..f12a4e9a4ed 100644 --- a/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java +++ b/solr/solrj-streaming/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java @@ -32,9 +32,9 @@ import org.apache.solr.client.solrj.impl.CloudHttp2SolrClient; import org.apache.solr.client.solrj.impl.CloudLegacySolrClient; import org.apache.solr.client.solrj.impl.CloudSolrClient; import org.apache.solr.client.solrj.impl.Http2SolrClient; -import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.impl.SolrClientBuilder; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.apache.solr.common.AlreadyClosedException; import org.apache.solr.common.util.IOUtils; import org.slf4j.Logger; @@ -50,9 +50,9 @@ public class SolrClientCache implements Closeable { private static final int MIN_TIMEOUT = 60000; private static final int minConnTimeout = Math.max( - Integer.getInteger(HttpClientUtil.PROP_CONNECTION_TIMEOUT, MIN_TIMEOUT), MIN_TIMEOUT); + Integer.getInteger(SolrHttpConstants.PROP_CONNECTION_TIMEOUT, MIN_TIMEOUT), MIN_TIMEOUT); private static final int minSocketTimeout = - Math.max(Integer.getInteger(HttpClientUtil.PROP_SO_TIMEOUT, MIN_TIMEOUT), MIN_TIMEOUT); + Math.max(Integer.getInteger(SolrHttpConstants.PROP_SO_TIMEOUT, MIN_TIMEOUT), MIN_TIMEOUT); private final Map<String, SolrClient> solrClients = new HashMap<>(); private final HttpClient apacheHttpClient; diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClient.java index 1bb31a7974e..de50b461c53 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClient.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClient.java @@ -54,7 +54,6 @@ import org.apache.solr.common.util.ExecutorUtil; import org.apache.solr.common.util.IOUtils; import org.apache.solr.common.util.NamedList; import org.apache.solr.common.util.SolrNamedThreadFactory; -import org.apache.solr.common.util.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; @@ -409,7 +408,7 @@ public class ConcurrentUpdateSolrClient extends SolrClient { } finally { try { if (response != null) { - Utils.consumeFully(response.getEntity()); + HttpClientUtil.consumeFully(response.getEntity()); } } catch (Exception e) { log.error("Error consuming and closing http response stream.", e); diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java index 0529029f14a..48abe93e63b 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/Http2SolrClient.java @@ -189,7 +189,7 @@ public class Http2SolrClient extends HttpSolrClientBase { private void applyHttpClientBuilderFactory() { String factoryClassName = - System.getProperty(HttpClientUtil.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY); + System.getProperty(SolrHttpConstants.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY); if (factoryClassName != null) { log.debug("Using Http Builder Factory: {}", factoryClassName); HttpClientBuilderFactory factory; @@ -1260,7 +1260,7 @@ public class Http2SolrClient extends HttpSolrClientBase { /* package-private for testing */ static SslContextFactory.Client getDefaultSslContextFactory() { - String checkPeerNameStr = System.getProperty(HttpClientUtil.SYS_PROP_CHECK_PEER_NAME); + String checkPeerNameStr = System.getProperty(SolrHttpConstants.SYS_PROP_CHECK_PEER_NAME); boolean sslCheckPeerName = !"false".equalsIgnoreCase(checkPeerNameStr); SslContextFactory.Client sslContextFactory = new SslContextFactory.Client(!sslCheckPeerName); diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientBuilderFactory.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientBuilderFactory.java index ed8cb32ec60..fa7752c6783 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientBuilderFactory.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientBuilderFactory.java @@ -22,6 +22,7 @@ import java.io.Closeable; * Factory interface for configuring {@linkplain SolrHttpClientBuilder}. This relies on the internal * HttpClient implementation and is subject to change. * + * @see SolrHttpConstants#SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY * @lucene.experimental */ public interface HttpClientBuilderFactory extends Closeable { diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java index 6aafaceef46..e95549720b1 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpClientUtil.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.lang.invoke.MethodHandles; import java.lang.reflect.InvocationTargetException; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.TimeUnit; @@ -40,6 +41,8 @@ import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpClient; import org.apache.http.client.config.RequestConfig; import org.apache.http.client.config.RequestConfig.Builder; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.protocol.HttpClientContext; import org.apache.http.config.Registry; import org.apache.http.config.RegistryBuilder; @@ -57,6 +60,8 @@ import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; import org.apache.http.protocol.HttpContext; import org.apache.http.protocol.HttpRequestExecutor; import org.apache.http.ssl.SSLContexts; +import org.apache.http.util.EntityUtils; +import org.apache.solr.common.SolrException; import org.apache.solr.common.params.ModifiableSolrParams; import org.apache.solr.common.params.SolrParams; import org.apache.solr.common.util.ObjectReleaseTracker; @@ -65,50 +70,27 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * Utility class for creating/configuring httpclient instances. + * Utility class for creating/configuring Apache {@link HttpClient} instances. * * <p>This class can touch internal HttpClient details and is subject to change. * * @lucene.experimental - * @deprecated Used to configure the Apache HTTP client. Please use the Http2 client + * @deprecated Used to configure the Apache HTTP client. Please use another client */ @Deprecated(since = "9.0") -public class HttpClientUtil { +public class HttpClientUtil implements SolrHttpConstants { private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - public static final int DEFAULT_CONNECT_TIMEOUT = 60000; - public static final int DEFAULT_SO_TIMEOUT = 600000; - public static final int DEFAULT_MAXCONNECTIONSPERHOST = 100000; - public static final int DEFAULT_MAXCONNECTIONS = 100000; - private static final int VALIDATE_AFTER_INACTIVITY_DEFAULT = 3000; private static final int EVICT_IDLE_CONNECTIONS_DEFAULT = 50000; private static final String VALIDATE_AFTER_INACTIVITY = "validateAfterInactivity"; private static final String EVICT_IDLE_CONNECTIONS = "evictIdleConnections"; - // Maximum connections allowed per host - public static final String PROP_MAX_CONNECTIONS_PER_HOST = "maxConnectionsPerHost"; - // Maximum total connections allowed - public static final String PROP_MAX_CONNECTIONS = "maxConnections"; // Retry http requests on error public static final String PROP_USE_RETRY = "retry"; // Allow compression (deflate,gzip) if server supports it public static final String PROP_ALLOW_COMPRESSION = "allowCompression"; - // Basic auth username - public static final String PROP_BASIC_AUTH_USER = "httpBasicAuthUser"; - // Basic auth password - public static final String PROP_BASIC_AUTH_PASS = "httpBasicAuthPassword"; - - /** - * System property consulted to determine if the default {@link SocketFactoryRegistryProvider} - * will require hostname validation of SSL Certificates. The default behavior is to enforce peer - * name validation. - * - * <p>This property will have no effect if {@link #setSocketFactoryRegistryProvider} is used to - * override the default {@link SocketFactoryRegistryProvider} - */ - public static final String SYS_PROP_CHECK_PEER_NAME = "solr.ssl.checkPeerName"; // * NOTE* The following params configure the default request config and this // is overridden by SolrJ clients. Use the setters on the SolrJ clients @@ -117,22 +99,6 @@ public class HttpClientUtil { // Follow redirects public static final String PROP_FOLLOW_REDIRECTS = "followRedirects"; - // socket timeout measured in ms, closes a socket if read - // takes longer than x ms to complete. throws - // java.net.SocketTimeoutException: Read timed out exception - public static final String PROP_SO_TIMEOUT = "socketTimeout"; - // connection timeout measures in ms, closes a socket if connection - // cannot be established within x ms. with a - // java.net.SocketTimeoutException: Connection timed out - public static final String PROP_CONNECTION_TIMEOUT = "connTimeout"; - - /** - * A Java system property to select the {@linkplain HttpClientBuilderFactory} used for configuring - * the {@linkplain HttpClientBuilder} instance by default. - */ - public static final String SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY = - "solr.httpclient.builder.factory"; - /** * A Java system property to select the {@linkplain SocketFactoryRegistryProvider} used for * configuring the Apache HTTP clients. @@ -196,6 +162,73 @@ public class HttpClientUtil { } } + public static <T> T executeGET( + HttpClient client, String url, Utils.InputStreamConsumer<T> consumer) throws SolrException { + return executeHttpMethod(client, url, consumer, new HttpGet(url)); + } + + public static <T> T executeHttpMethod( + HttpClient client, + String url, + Utils.InputStreamConsumer<T> consumer, + HttpRequestBase httpMethod) { + T result = null; + HttpResponse rsp; + try { + rsp = client.execute(httpMethod); + } catch (IOException e) { + log.error("Error in request to url : {}", url, e); + throw new SolrException(SolrException.ErrorCode.UNKNOWN, "Error sending request"); + } + int statusCode = rsp.getStatusLine().getStatusCode(); + if (statusCode != 200) { + try { + log.error( + "Failed a request to: {}, status: {}, body: {}", + url, + rsp.getStatusLine(), + EntityUtils.toString(rsp.getEntity(), StandardCharsets.UTF_8)); // nowarn + } catch (IOException e) { + log.error("could not print error", e); + } + throw new SolrException(SolrException.ErrorCode.getErrorCode(statusCode), "Unknown error"); + } + HttpEntity entity = rsp.getEntity(); + try { + InputStream is = entity.getContent(); + if (consumer != null) { + + result = consumer.accept(is); + } + } catch (IOException e) { + throw new SolrException(SolrException.ErrorCode.UNKNOWN, e); + } finally { + consumeFully(entity); + } + return result; + } + + /** + * If the passed entity has content, make sure it is fully read and closed. + * + * @param entity to consume or null + */ + public static void consumeFully(HttpEntity entity) { + if (entity != null) { + try { + // make sure the stream is full read + Utils.readFully(entity.getContent()); + } catch (UnsupportedOperationException e) { + // nothing to do then + } catch (IOException e) { + // quiet + } finally { + // close the stream + EntityUtils.consumeQuietly(entity); + } + } + } + public abstract static class SocketFactoryRegistryProvider { /** Must be non-null */ public abstract Registry<ConnectionSocketFactory> getSocketFactoryRegistry(); diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java index bb6460c79b8..d73356ccc68 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java @@ -736,7 +736,7 @@ public class HttpSolrClient extends BaseHttpSolrClient { "IOException occurred when talking to server at: " + getBaseURL(), e); } finally { if (shouldClose) { - Utils.consumeFully(entity); + HttpClientUtil.consumeFully(entity); } } } diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClientBuilderBase.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClientBuilderBase.java index 1b4f70e62f8..b2b2d4a6900 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClientBuilderBase.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClientBuilderBase.java @@ -130,7 +130,7 @@ public abstract class HttpSolrClientBuilderBase< public long getIdleTimeoutMillis() { return idleTimeoutMillis != null && idleTimeoutMillis > 0 ? idleTimeoutMillis - : HttpClientUtil.DEFAULT_SO_TIMEOUT; + : SolrHttpConstants.DEFAULT_SO_TIMEOUT; } /** The max time a connection can take to connect to destinations. */ @@ -143,7 +143,7 @@ public abstract class HttpSolrClientBuilderBase< public long getConnectionTimeoutMillis() { return connectionTimeoutMillis != null && connectionTimeoutMillis > 0 ? connectionTimeoutMillis - : HttpClientUtil.DEFAULT_CONNECT_TIMEOUT; + : SolrHttpConstants.DEFAULT_CONNECT_TIMEOUT; } /** Set a timeout for requests to receive a response. */ diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java index 0d1231baa74..3b424d6f47c 100644 --- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/PreemptiveBasicAuthClientBuilderFactory.java @@ -79,9 +79,9 @@ public class PreemptiveBasicAuthClientBuilderFactory implements HttpClientBuilde @Override public void setup(Http2SolrClient client) { final String basicAuthUser = - CREDENTIAL_RESOLVER.defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_USER); + CREDENTIAL_RESOLVER.defaultParams.get(SolrHttpConstants.PROP_BASIC_AUTH_USER); final String basicAuthPass = - CREDENTIAL_RESOLVER.defaultParams.get(HttpClientUtil.PROP_BASIC_AUTH_PASS); + CREDENTIAL_RESOLVER.defaultParams.get(SolrHttpConstants.PROP_BASIC_AUTH_PASS); this.setup(client, basicAuthUser, basicAuthPass); } @@ -158,9 +158,9 @@ public class PreemptiveBasicAuthClientBuilderFactory implements HttpClientBuilde defaultParams = new MapSolrParams( Map.of( - HttpClientUtil.PROP_BASIC_AUTH_USER, + SolrHttpConstants.PROP_BASIC_AUTH_USER, ss.get(0), - HttpClientUtil.PROP_BASIC_AUTH_PASS, + SolrHttpConstants.PROP_BASIC_AUTH_PASS, ss.get(1))); } else if (configFile != null) { Properties defaultProps = new Properties(); diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/SolrHttpConstants.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/SolrHttpConstants.java new file mode 100644 index 00000000000..8c207364594 --- /dev/null +++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/SolrHttpConstants.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.solr.client.solrj.impl; + +/** Constants for HTTP Solr interaction. */ +public interface SolrHttpConstants { + int DEFAULT_CONNECT_TIMEOUT = 60000; + int DEFAULT_SO_TIMEOUT = 600000; + int DEFAULT_MAXCONNECTIONSPERHOST = 100000; + int DEFAULT_MAXCONNECTIONS = 100000; + + /** + * Socket timeout measured in ms, closes a socket if read takes longer than x ms to complete. + * throws {@link java.net.SocketTimeoutException}: Read timed out exception + */ + String PROP_SO_TIMEOUT = "socketTimeout"; + + /** + * connection timeout measures in ms, closes a socket if connection cannot be established within x + * ms. with a {@link java.net.SocketTimeoutException}: Connection timed out + */ + String PROP_CONNECTION_TIMEOUT = "connTimeout"; + + /** Maximum connections allowed per host */ + String PROP_MAX_CONNECTIONS_PER_HOST = "maxConnectionsPerHost"; + + /** Maximum total connections allowed */ + String PROP_MAX_CONNECTIONS = "maxConnections"; + + /** + * A Java system property to select the {@linkplain HttpClientBuilderFactory} used for configuring + * HTTP based SolrClients. + */ + String SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY = "solr.httpclient.builder.factory"; + + /** + * System property consulted to determine if HTTP based SolrClients will require hostname + * validation of SSL Certificates. The default behavior is to enforce peer name validation. + */ + String SYS_PROP_CHECK_PEER_NAME = "solr.ssl.checkPeerName"; + + /** Basic auth username */ + String PROP_BASIC_AUTH_USER = "httpBasicAuthUser"; + + /** Basic auth password */ + String PROP_BASIC_AUTH_PASS = "httpBasicAuthPassword"; +} diff --git a/solr/solrj/src/java/org/apache/solr/common/util/Utils.java b/solr/solrj/src/java/org/apache/solr/common/util/Utils.java index 552d62d9a08..afcb82f392c 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/Utils.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/Utils.java @@ -66,12 +66,6 @@ import java.util.function.Function; import java.util.function.Predicate; import java.util.regex.Matcher; import java.util.regex.Pattern; -import org.apache.http.HttpEntity; -import org.apache.http.HttpResponse; -import org.apache.http.client.HttpClient; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpRequestBase; -import org.apache.http.util.EntityUtils; import org.apache.solr.common.IteratorWriter; import org.apache.solr.common.LinkedHashMapWriter; import org.apache.solr.common.MapWriter; @@ -623,27 +617,6 @@ public class Utils { } else throw new RuntimeException("must be a NamedList or Map"); } - /** - * If the passed entity has content, make sure it is fully read and closed. - * - * @param entity to consume or null - */ - public static void consumeFully(HttpEntity entity) { - if (entity != null) { - try { - // make sure the stream is full read - readFully(entity.getContent()); - } catch (UnsupportedOperationException e) { - // nothing to do then - } catch (IOException e) { - // quiet - } finally { - // close the stream - EntityUtils.consumeQuietly(entity); - } - } - } - /** * Make sure the InputStream is fully read. * @@ -813,49 +786,6 @@ public class Utils { }; } - public static <T> T executeGET(HttpClient client, String url, InputStreamConsumer<T> consumer) - throws SolrException { - return executeHttpMethod(client, url, consumer, new HttpGet(url)); - } - - public static <T> T executeHttpMethod( - HttpClient client, String url, InputStreamConsumer<T> consumer, HttpRequestBase httpMethod) { - T result = null; - HttpResponse rsp = null; - try { - rsp = client.execute(httpMethod); - } catch (IOException e) { - log.error("Error in request to url : {}", url, e); - throw new SolrException(SolrException.ErrorCode.UNKNOWN, "Error sending request"); - } - int statusCode = rsp.getStatusLine().getStatusCode(); - if (statusCode != 200) { - try { - log.error( - "Failed a request to: {}, status: {}, body: {}", - url, - rsp.getStatusLine(), - EntityUtils.toString(rsp.getEntity(), StandardCharsets.UTF_8)); // nowarn - } catch (IOException e) { - log.error("could not print error", e); - } - throw new SolrException(SolrException.ErrorCode.getErrorCode(statusCode), "Unknown error"); - } - HttpEntity entity = rsp.getEntity(); - try { - InputStream is = entity.getContent(); - if (consumer != null) { - - result = consumer.accept(is); - } - } catch (IOException e) { - throw new SolrException(SolrException.ErrorCode.UNKNOWN, e); - } finally { - Utils.consumeFully(entity); - } - return result; - } - /** * Convert the input object to a map, writing only those fields annotated with a {@link * JsonProperty} annotation diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrSchemalessExampleTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrSchemalessExampleTest.java index e66d8362631..fd9e6ddcfc7 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrSchemalessExampleTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrSchemalessExampleTest.java @@ -35,7 +35,6 @@ import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpSolrClient; import org.apache.solr.client.solrj.response.QueryResponse; import org.apache.solr.common.SolrDocument; -import org.apache.solr.common.util.Utils; import org.apache.solr.util.ExternalPaths; import org.junit.BeforeClass; import org.junit.Test; @@ -89,7 +88,7 @@ public class SolrSchemalessExampleTest extends SolrExampleTestsBase { new InputStreamEntity(new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8)), -1)); HttpResponse response = httpClient.execute(post, HttpClientUtil.createNewHttpClientRequestContext()); - Utils.consumeFully(response.getEntity()); + HttpClientUtil.consumeFully(response.getEntity()); assertEquals(200, response.getStatusLine().getStatusCode()); client.commit(); assertNumFound("*:*", 2); diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java index 96458b275a3..ab9bf93540b 100644 --- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java +++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/Http2SolrClientTest.java @@ -525,7 +525,7 @@ public class Http2SolrClientTest extends HttpSolrClientTestBase { System.setProperty( PreemptiveBasicAuthClientBuilderFactory.SYS_PROP_BASIC_AUTH_CREDENTIALS, "foo:bar"); System.setProperty( - HttpClientUtil.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY, + SolrHttpConstants.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY, PreemptiveBasicAuthClientBuilderFactory.class.getName()); // Hack to ensure we get a new set of parameters for this test PreemptiveBasicAuthClientBuilderFactory.setDefaultSolrParams( @@ -553,7 +553,7 @@ public class Http2SolrClientTest extends HttpSolrClientTestBase { authorizationHeader); } finally { System.clearProperty(PreemptiveBasicAuthClientBuilderFactory.SYS_PROP_BASIC_AUTH_CREDENTIALS); - System.clearProperty(HttpClientUtil.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY); + System.clearProperty(SolrHttpConstants.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY); PreemptiveBasicAuthClientBuilderFactory.setDefaultSolrParams( new MapSolrParams(new HashMap<>())); } @@ -631,7 +631,7 @@ public class Http2SolrClientTest extends HttpSolrClientTestBase { @Test public void testBadHttpFactory() { - System.setProperty(HttpClientUtil.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY, "FakeClassName"); + System.setProperty(SolrHttpConstants.SYS_PROP_HTTP_CLIENT_BUILDER_FACTORY, "FakeClassName"); try { SolrClient client = new Http2SolrClient.Builder(getBaseUrl() + DEBUG_SERVLET_PATH) diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudAuthTestCase.java b/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudAuthTestCase.java index 1458e7486ab..6c1cce31d57 100644 --- a/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudAuthTestCase.java +++ b/solr/test-framework/src/java/org/apache/solr/cloud/SolrCloudAuthTestCase.java @@ -41,6 +41,7 @@ import org.apache.http.client.methods.HttpGet; import org.apache.http.message.AbstractHttpMessage; import org.apache.http.message.BasicHeader; import org.apache.http.util.EntityUtils; +import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.common.util.StrUtils; import org.apache.solr.common.util.Utils; import org.apache.solr.embedded.JettySolrRunner; @@ -304,7 +305,7 @@ public class SolrCloudAuthTestCase extends SolrCloudTestCase { } catch (Exception e) { fail("Invalid json " + s); } - Utils.consumeFully(rsp.getEntity()); + HttpClientUtil.consumeFully(rsp.getEntity()); Object actual = Utils.getObjectByPath(m, true, hierarchy); if (expected instanceof Predicate) { @SuppressWarnings({"rawtypes"}) diff --git a/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java b/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java index 4b0c7c47529..64f02bf5775 100644 --- a/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java +++ b/solr/test-framework/src/java/org/apache/solr/util/SSLTestConfig.java @@ -40,8 +40,8 @@ import org.apache.http.ssl.SSLContextBuilder; import org.apache.http.ssl.SSLContexts; import org.apache.lucene.util.Constants; import org.apache.solr.client.solrj.embedded.SSLConfig; -import org.apache.solr.client.solrj.impl.HttpClientUtil; import org.apache.solr.client.solrj.impl.HttpClientUtil.SocketFactoryRegistryProvider; +import org.apache.solr.client.solrj.impl.SolrHttpConstants; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.security.CertificateUtils; import org.eclipse.jetty.util.ssl.SslContextFactory; @@ -101,7 +101,7 @@ public class SSLTestConfig { * @param clientAuth - whether client authentication should be required. * @param checkPeerName - whether the client should validate the 'peer name' of the SSL * Certificate (and which testing Cert should be used) - * @see HttpClientUtil#SYS_PROP_CHECK_PEER_NAME + * @see SolrHttpConstants#SYS_PROP_CHECK_PEER_NAME */ public SSLTestConfig(boolean useSsl, boolean clientAuth, boolean checkPeerName) { this.useSsl = useSsl;
