You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by an...@apache.org on 2016/04/08 01:25:00 UTC

[1/3] lucene-solr:master: SOLR-8097: Implement builder pattern design for constructing SolrJ clients and deprecate direct construction of clients

Repository: lucene-solr
Updated Branches:
  refs/heads/master 1848477bd -> b02b026b7


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/HttpSolrClient.java
----------------------------------------------------------------------
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 18038c2..9b0cf8d 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
@@ -30,7 +30,6 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Set;
-import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 
@@ -41,7 +40,6 @@ import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.NameValuePair;
 import org.apache.http.client.HttpClient;
-import org.apache.http.client.config.RequestConfig.Builder;
 import org.apache.http.client.entity.UrlEncodedFormEntity;
 import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
 import org.apache.http.client.methods.HttpGet;
@@ -55,7 +53,6 @@ import org.apache.http.entity.InputStreamEntity;
 import org.apache.http.entity.mime.FormBodyPart;
 import org.apache.http.entity.mime.HttpMultipartMode;
 import org.apache.http.entity.mime.MultipartEntity;
-import org.apache.http.entity.mime.MultipartEntityBuilder;
 import org.apache.http.entity.mime.content.InputStreamBody;
 import org.apache.http.entity.mime.content.StringBody;
 import org.apache.http.message.BasicHeader;
@@ -160,20 +157,34 @@ public class HttpSolrClient extends SolrClient {
    *          The URL of the Solr server. For example, "
    *          <code>http://localhost:8983/solr/</code>" if you are using the
    *          standard distribution Solr webapp on your local machine.
+   * @deprecated use {@link Builder} instead.
    */
+  @Deprecated
   public HttpSolrClient(String baseURL) {
     this(baseURL, null, new BinaryResponseParser());
   }
   
+  /**
+   * @deprecated use {@link Builder} instead.
+   */
+  @Deprecated
   public HttpSolrClient(String baseURL, HttpClient client) {
     this(baseURL, client, new BinaryResponseParser());
   }
   
-  
+  /**
+   * @deprecated use {@link Builder} instead.
+   */
+  @Deprecated
   public HttpSolrClient(String baseURL, HttpClient client, ResponseParser parser) {
     this(baseURL, client, parser, false);
   }
   
+  /**
+   * @deprecated use {@link Builder} instead.  This will soon be a 'protected'
+   * method, and will only be available for use in implementing subclasses.
+   */
+  @Deprecated
   public HttpSolrClient(String baseURL, HttpClient client, ResponseParser parser, boolean allowCompression) {
     this.baseUrl = baseURL;
     if (baseUrl.endsWith("/")) {
@@ -479,7 +490,7 @@ public class HttpSolrClient extends SolrClient {
   protected NamedList<Object> executeMethod(HttpRequestBase method, final ResponseParser processor) throws SolrServerException {
     method.addHeader("User-Agent", AGENT);
  
-    Builder requestConfigBuilder = HttpClientUtil.createDefaultRequestConfigBuilder();
+    org.apache.http.client.config.RequestConfig.Builder requestConfigBuilder = HttpClientUtil.createDefaultRequestConfigBuilder();
     if (soTimeout != null) {
       requestConfigBuilder.setSocketTimeout(soTimeout);
     }
@@ -732,4 +743,60 @@ public class HttpSolrClient extends SolrClient {
       super(code, "Error from server at " + remoteHost + ": " + msg, th);
     }
   }
+  
+  /**
+   * Constructs {@link HttpSolrClient} instances from provided configuration.
+   */
+  public static class Builder {
+    private String baseSolrUrl;
+    private HttpClient httpClient;
+    private ResponseParser responseParser;
+    private boolean compression;
+    
+    /**
+     * Create a Builder object, based on the provided Solr URL.
+     * 
+     * By default, compression is not enabled in created HttpSolrClient objects.
+     * 
+     * @param baseSolrUrl the base URL of the Solr server that will be targeted by any created clients.
+     */
+    public Builder(String baseSolrUrl) {
+      this.baseSolrUrl = baseSolrUrl;
+      this.responseParser = new BinaryResponseParser();
+    }
+    
+    /**
+     * Provides a {@link HttpClient} for the builder to use when creating clients.
+     */
+    public Builder withHttpClient(HttpClient httpClient) {
+      this.httpClient = httpClient;
+      return this;
+    }
+    
+    /**
+     * Provides a {@link ResponseParser} for created clients to use when handling requests.
+     */
+    public Builder withResponseParser(ResponseParser responseParser) {
+      this.responseParser = responseParser;
+      return this;
+    }
+    
+    /**
+     * Chooses whether created {@link HttpSolrClient}s use compression by default.
+     */
+    public Builder allowCompression(boolean compression) {
+      this.compression = compression;
+      return this;
+    }
+    
+    /**
+     * Create a {@link HttpSolrClient} based on provided configuration.
+     */
+    public HttpSolrClient build() {
+      if (baseSolrUrl == null) {
+        throw new IllegalArgumentException("Cannot create HttpSolrClient without a valid baseSolrUrl!");
+      }
+      return new HttpSolrClient(baseSolrUrl, httpClient, responseParser, compression);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
index fabb933..eaf593e 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttpSolrClient.java
@@ -16,30 +16,44 @@
  */
 package org.apache.solr.client.solrj.impl;
 
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.net.ConnectException;
+import java.net.MalformedURLException;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicInteger;
+
 import org.apache.http.client.HttpClient;
-import org.apache.solr.client.solrj.*;
+import org.apache.solr.client.solrj.ResponseParser;
+import org.apache.solr.client.solrj.SolrClient;
+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.request.IsUpdateRequest;
 import org.apache.solr.client.solrj.request.RequestWriter;
 import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SolrjNamedThreadFactory;
-import org.apache.solr.common.SolrException;
 import org.slf4j.MDC;
 
-import java.io.IOException;
-import java.lang.ref.WeakReference;
-import java.net.ConnectException;
-import java.net.MalformedURLException;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.util.concurrent.*;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.*;
-
 /**
  * LBHttpSolrClient or "LoadBalanced HttpSolrClient" is a load balancing wrapper around
  * {@link HttpSolrClient}. This is useful when you
@@ -209,19 +223,31 @@ public class LBHttpSolrClient extends SolrClient {
     }
   }
 
+  /**
+   * @deprecated use {@link Builder} instead.
+   */
+  @Deprecated
   public LBHttpSolrClient(String... solrServerUrls) throws MalformedURLException {
     this(null, solrServerUrls);
   }
   
-  /** The provided httpClient should use a multi-threaded connection manager */ 
+  /**
+   * The provided httpClient should use a multi-threaded connection manager
+   * @deprecated use {@link Builder} instead.
+   */ 
+  @Deprecated
   public LBHttpSolrClient(HttpClient httpClient, String... solrServerUrl) {
     this(httpClient, new BinaryResponseParser(), solrServerUrl);
   }
 
-  /** The provided httpClient should use a multi-threaded connection manager */  
+  /**
+   * The provided httpClient should use a multi-threaded connection manager
+   * @deprecated use {@link Builder} instead.  This will soon be a protected
+   * method and will only be available for use in implementing subclasses.
+   */
+  @Deprecated
   public LBHttpSolrClient(HttpClient httpClient, ResponseParser parser, String... solrServerUrl) {
     clientIsInternal = (httpClient == null);
-    this.parser = parser;
     if (httpClient == null) {
       ModifiableSolrParams params = new ModifiableSolrParams();
       if (solrServerUrl.length > 1) {
@@ -234,6 +260,9 @@ public class LBHttpSolrClient extends SolrClient {
     } else {
       this.httpClient = httpClient;
     }
+    
+    this.parser = parser;
+    
     for (String s : solrServerUrl) {
       ServerWrapper wrapper = new ServerWrapper(makeSolrClient(s));
       aliveServers.put(wrapper.getKey(), wrapper);
@@ -263,7 +292,10 @@ public class LBHttpSolrClient extends SolrClient {
   }
 
   protected HttpSolrClient makeSolrClient(String server) {
-    HttpSolrClient client = new HttpSolrClient(server, httpClient, parser);
+    HttpSolrClient client = new HttpSolrClient.Builder(server)
+        .withHttpClient(httpClient)
+        .withResponseParser(parser)
+        .build();
     if (connectionTimeout != null) {
       client.setConnectionTimeout(connectionTimeout);
     }
@@ -746,4 +778,64 @@ public class LBHttpSolrClient extends SolrClient {
   private static final int CHECK_INTERVAL = 60 * 1000; //1 minute between checks
   private static final int NONSTANDARD_PING_LIMIT = 5;  // number of times we'll ping dead servers not in the server list
 
+  /**
+   * Constructs {@link LBHttpSolrClient} instances from provided configuration.
+   */
+  public static class Builder {
+    private final List<String> baseSolrUrls;
+    private HttpClient httpClient;
+    private ResponseParser responseParser;
+    
+    public Builder() {
+      this.baseSolrUrls = new ArrayList<String>();
+      this.responseParser = new BinaryResponseParser();
+    }
+    
+    /**
+     * Provide a Solr endpoint to be used when configuring {@link LBHttpSolrClient} instances.
+     * 
+     * Method may be called multiple times.  All provided values will be used.
+     */
+    public Builder withBaseSolrUrl(String baseSolrUrl) {
+      this.baseSolrUrls.add(baseSolrUrl);
+      return this;
+    }
+    
+    /**
+     * Provide Solr endpoints to be used when configuring {@link LBHttpSolrClient} instances.
+     * 
+     * Method may be called multiple times.  All provided values will be used.
+     */
+    public Builder withBaseSolrUrls(String... solrUrls) {
+      for (String baseSolrUrl : solrUrls) {
+        this.baseSolrUrls.add(baseSolrUrl);
+      }
+      return this;
+    }
+    
+    
+    /**
+     * Provides a {@link HttpClient} for the builder to use when creating clients.
+     */
+    public Builder withHttpClient(HttpClient httpClient) {
+      this.httpClient = httpClient;
+      return this;
+    }
+    
+    /**
+     * Provides a {@link ResponseParser} for created clients to use when handling requests.
+     */
+    public Builder withResponseParser(ResponseParser responseParser) {
+      this.responseParser = responseParser;
+      return this;
+    }
+    
+    /**
+     * Create a {@link HttpSolrClient} based on provided configuration.
+     */
+    public LBHttpSolrClient build() {
+      final String[] baseUrlArray = new String[baseSolrUrls.size()];
+      return new LBHttpSolrClient(httpClient, responseParser, baseSolrUrls.toArray(baseUrlArray));
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java
index e544c10..cd992a4 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/SolrClientCache.java
@@ -21,7 +21,7 @@ import java.io.Serializable;
 import java.lang.invoke.MethodHandles;
 import java.util.Map;
 import java.util.HashMap;
-import java.util.Iterator;
+
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
@@ -44,7 +44,9 @@ public class SolrClientCache implements Serializable {
     if (solrClients.containsKey(zkHost)) {
       client = (CloudSolrClient) solrClients.get(zkHost);
     } else {
-      client = new CloudSolrClient(zkHost);
+      client = new CloudSolrClient.Builder()
+          .withZkHost(zkHost)
+          .build();
       client.connect();
       solrClients.put(zkHost, client);
     }
@@ -57,7 +59,8 @@ public class SolrClientCache implements Serializable {
     if (solrClients.containsKey(host)) {
       client = (HttpSolrClient) solrClients.get(host);
     } else {
-      client = new HttpSolrClient(host);
+      client = new HttpSolrClient.Builder(host)
+          .build();
       solrClients.put(host, client);
     }
     return client;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/DatabaseMetaDataImpl.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/DatabaseMetaDataImpl.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/DatabaseMetaDataImpl.java
index d316c83..53f5c8d 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/DatabaseMetaDataImpl.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/sql/DatabaseMetaDataImpl.java
@@ -29,7 +29,7 @@ import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.common.util.SimpleOrderedMap;
 
@@ -119,7 +119,7 @@ class DatabaseMetaDataImpl implements DatabaseMetaData {
     for (String node : liveNodes) {
       try {
         String nodeURL = cloudSolrClient.getZkStateReader().getBaseUrlForNodeName(node);
-        solrClient = new HttpSolrClient(nodeURL);
+        solrClient = new Builder(nodeURL).build();
 
         QueryResponse rsp = solrClient.query(sysQuery);
         return String.valueOf(((SimpleOrderedMap) rsp.getResponse().get("lucene")).get("solr-spec-version"));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java
index 07e6cb1..c9c7b22 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/CloudSolrStream.java
@@ -34,6 +34,7 @@ import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
 import org.apache.solr.client.solrj.io.SolrClientCache;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.ComparatorOrder;
@@ -236,7 +237,9 @@ public class CloudSolrStream extends TupleStream implements Expressible {
     if(this.cache != null) {
       this.cloudSolrClient = this.cache.getCloudSolrClient(zkHost);
     } else {
-      this.cloudSolrClient = new CloudSolrClient(zkHost);
+      this.cloudSolrClient = new Builder()
+          .withZkHost(zkHost)
+          .build();
       this.cloudSolrClient.connect();
     }
     constructStreams();
@@ -476,4 +479,4 @@ public class CloudSolrStream extends TupleStream implements Expressible {
       }
     }
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
index e4ae04c..3474257 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/FacetStream.java
@@ -19,7 +19,6 @@ package org.apache.solr.client.solrj.io.stream;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.ArrayList;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -27,6 +26,7 @@ import java.util.Collections;
 import java.util.Map.Entry;
 
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
 import org.apache.solr.client.solrj.io.SolrClientCache;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.ComparatorOrder;
@@ -281,7 +281,9 @@ public class FacetStream extends TupleStream implements Expressible  {
     if(cache != null) {
       cloudSolrClient = cache.getCloudSolrClient(zkHost);
     } else {
-      cloudSolrClient = new CloudSolrClient(zkHost);
+      cloudSolrClient = new Builder()
+          .withZkHost(zkHost)
+          .build();
     }
 
     FieldComparator[] adjustedSorts = adjustSorts(buckets, bucketSorts);
@@ -479,4 +481,4 @@ public class FacetStream extends TupleStream implements Expressible  {
       return bucketSorts[0];
     }
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
index 1c149cc..7ff8a4e 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/SolrStream.java
@@ -86,7 +86,7 @@ public class SolrStream extends TupleStream {
 
 
     if(cache == null) {
-      client = new HttpSolrClient(baseUrl);
+      client = new HttpSolrClient.Builder(baseUrl).build();
     } else {
       client = cache.getHttpSolrClient(baseUrl);
     }
@@ -230,4 +230,4 @@ public class SolrStream extends TupleStream {
 
     return fields;
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java
index 478bc56..6ef49ea 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/StatsStream.java
@@ -25,6 +25,7 @@ import java.util.Map;
 import java.util.Map.Entry;
 
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
 import org.apache.solr.client.solrj.io.SolrClientCache;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.StreamComparator;
@@ -162,7 +163,9 @@ public class StatsStream extends TupleStream implements Expressible  {
     if(cache != null) {
       cloudSolrClient = cache.getCloudSolrClient(zkHost);
     } else {
-      cloudSolrClient = new CloudSolrClient(zkHost);
+      cloudSolrClient = new Builder()
+          .withZkHost(zkHost)
+          .build();
     }
 
     ModifiableSolrParams params = getParams(this.props);
@@ -290,4 +293,4 @@ public class StatsStream extends TupleStream implements Expressible  {
       map.put(stat+"("+field+")", val);
     }
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TopicStream.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TopicStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TopicStream.java
index a52e8f9..e3434fc 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TopicStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TopicStream.java
@@ -33,7 +33,7 @@ import java.util.TreeSet;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Future;
 
-import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.ComparatorOrder;
@@ -218,7 +218,9 @@ public class TopicStream extends CloudSolrStream implements Expressible  {
     if(cache != null) {
       cloudSolrClient = cache.getCloudSolrClient(zkHost);
     } else {
-      cloudSolrClient = new CloudSolrClient(zkHost);
+      cloudSolrClient = new Builder()
+          .withZkHost(zkHost)
+          .build();
       this.cloudSolrClient.connect();
     }
 
@@ -474,4 +476,4 @@ public class TopicStream extends CloudSolrStream implements Expressible  {
       throw new IOException(e);
     }
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java
index 67e52e6..9ddd381 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/UpdateStream.java
@@ -26,6 +26,7 @@ import java.util.Map;
 
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
 import org.apache.solr.client.solrj.io.SolrClientCache;
 import org.apache.solr.client.solrj.io.Tuple;
 import org.apache.solr.client.solrj.io.comp.StreamComparator;
@@ -219,7 +220,9 @@ public class UpdateStream extends TupleStream implements Expressible {
     if(this.cache != null) {
       this.cloudSolrClient = this.cache.getCloudSolrClient(zkHost);
     } else {
-      this.cloudSolrClient = new CloudSolrClient(zkHost);
+      this.cloudSolrClient = new Builder()
+          .withZkHost(zkHost)
+          .build();
       this.cloudSolrClient.connect();
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java
index 1d70cd9..dc53517 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleBinaryTest.java
@@ -40,7 +40,7 @@ public class SolrExampleBinaryTest extends SolrExampleTests {
     try {
       // setup the server...
       String url = jetty.getBaseUrl().toString() + "/collection1";
-      HttpSolrClient client = new HttpSolrClient( url );
+      HttpSolrClient client = getHttpSolrClient(url);
       client.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
       client.setUseMultiPartPost(random().nextBoolean());
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
index 6547bc1..1dd074e 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleTests.java
@@ -220,7 +220,7 @@ abstract public class SolrExampleTests extends SolrExampleTestsBase
     if (jetty != null) {
       // check system wide system handler + "/admin/info/system"
       String url = jetty.getBaseUrl().toString();
-      try (HttpSolrClient adminClient = new HttpSolrClient(url)) {
+      try (HttpSolrClient adminClient = getHttpSolrClient(url)) {
         SolrQuery q = new SolrQuery();
         q.set("qt", "/admin/info/system");
         QueryResponse rsp = adminClient.query(q);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java
index 338e449..92ab1ec 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExampleXMLTest.java
@@ -37,7 +37,7 @@ public class SolrExampleXMLTest extends SolrExampleTests {
   public SolrClient createNewSolrClient() {
     try {
       String url = jetty.getBaseUrl().toString() + "/collection1";
-      HttpSolrClient client = new HttpSolrClient(url);
+      HttpSolrClient client = getHttpSolrClient(url);
       client.setUseMultiPartPost(random().nextBoolean());
       client.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
       client.setParser(new XMLResponseParser());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java
index 9fbaffb..6b92213 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrExceptionTest.java
@@ -16,6 +16,8 @@
  */
 package org.apache.solr.client.solrj;
 
+import static org.apache.solr.SolrTestCaseJ4.getHttpSolrClient;
+
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
@@ -38,7 +40,7 @@ public class SolrExceptionTest extends LuceneTestCase {
       // switched to a local address to avoid going out on the net, ns lookup issues, etc.
       // set a 1ms timeout to let the connection fail faster.
       httpClient = HttpClientUtil.createClient(null);
-      try (HttpSolrClient client = new HttpSolrClient("http://[ff01::114]:11235/solr/", httpClient)) {
+      try (HttpSolrClient client = getHttpSolrClient("http://[ff01::114]:11235/solr/", httpClient)) {
         client.setConnectionTimeout(1);
         SolrQuery query = new SolrQuery("test123");
         client.query(query);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/SolrSchemalessExampleTest.java
----------------------------------------------------------------------
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 317d4cd..443e59e 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
@@ -134,7 +134,7 @@ public class SolrSchemalessExampleTest extends SolrExampleTestsBase {
     try {
       // setup the server...
       String url = jetty.getBaseUrl().toString() + "/collection1";
-      HttpSolrClient client = new HttpSolrClient(url);
+      HttpSolrClient client = getHttpSolrClient(url);
       client.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
       client.setUseMultiPartPost(random().nextBoolean());
       

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java b/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java
index 70cd77d..64e90c3 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/TestLBHttpSolrClient.java
@@ -109,7 +109,7 @@ public class TestLBHttpSolrClient extends SolrTestCaseJ4 {
       docs.add(doc);
     }
     SolrResponseBase resp;
-    try (HttpSolrClient client = new HttpSolrClient(solrInstance.getUrl(), httpClient)) {
+    try (HttpSolrClient client = getHttpSolrClient(solrInstance.getUrl(), httpClient)) {
       resp = client.add(docs);
       assertEquals(0, resp.getStatus());
       resp = client.commit();
@@ -133,7 +133,7 @@ public class TestLBHttpSolrClient extends SolrTestCaseJ4 {
     for (int i = 0; i < solr.length; i++) {
       s[i] = solr[i].getUrl();
     }
-    LBHttpSolrClient client = new LBHttpSolrClient(httpClient, s);
+    LBHttpSolrClient client = getLBHttpSolrClient(httpClient, s);
     client.setAliveCheckInterval(500);
     SolrQuery solrQuery = new SolrQuery("*:*");
     Set<String> names = new HashSet<>();
@@ -171,7 +171,7 @@ public class TestLBHttpSolrClient extends SolrTestCaseJ4 {
   }
 
   public void testTwoServers() throws Exception {
-    LBHttpSolrClient client = new LBHttpSolrClient(httpClient, solr[0].getUrl(), solr[1].getUrl());
+    LBHttpSolrClient client = getLBHttpSolrClient(httpClient, solr[0].getUrl(), solr[1].getUrl());
     client.setAliveCheckInterval(500);
     SolrQuery solrQuery = new SolrQuery("*:*");
     QueryResponse resp = null;
@@ -206,7 +206,7 @@ public class TestLBHttpSolrClient extends SolrTestCaseJ4 {
 
     CloseableHttpClient myHttpClient = HttpClientUtil.createClient(null);
     try {
-      LBHttpSolrClient client = new LBHttpSolrClient(myHttpClient, s);
+      LBHttpSolrClient client = getLBHttpSolrClient(myHttpClient, s);
       client.setConnectionTimeout(250);
       client.setSoTimeout(250);
       client.setAliveCheckInterval(500);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java
index d8347ce..a8832e7 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleJettyTest.java
@@ -55,7 +55,7 @@ public class SolrExampleJettyTest extends SolrExampleTests {
     try {
       // setup the server...
       String url = "http" + (isSSLMode() ? "s" : "") +  "://127.0.0.1/?core=xxx";
-      HttpSolrClient client = new HttpSolrClient(url);
+      HttpSolrClient client = getHttpSolrClient(url);
       Assert.fail("HttpSolrServer should not allow a path with a parameter: " + client.getBaseURL());
     }
     catch( Exception ex ) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java
index c3fa784..093238d 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/embedded/SolrExampleStreamingTest.java
@@ -80,14 +80,8 @@ public class SolrExampleStreamingTest extends SolrExampleTests {
   public void testWaitOptions() throws Exception {
     // SOLR-3903
     final List<Throwable> failures = new ArrayList<>();
-    try (ConcurrentUpdateSolrClient concurrentClient = new ConcurrentUpdateSolrClient
-      (jetty.getBaseUrl().toString() + "/collection1", 2, 2) {
-        @Override
-        public void handleError(Throwable ex) {
-          failures.add(ex);
-        }
-      }) {
-
+    final String serverUrl = jetty.getBaseUrl().toString() + "/collection1";
+    try (ConcurrentUpdateSolrClient concurrentClient = new FailureRecordingConcurrentUpdateSolrClient(serverUrl, 2, 2)) {
       int docId = 42;
       for (UpdateRequest.ACTION action : EnumSet.allOf(UpdateRequest.ACTION.class)) {
         for (boolean waitSearch : Arrays.asList(true, false)) {
@@ -110,5 +104,18 @@ public class SolrExampleStreamingTest extends SolrExampleTests {
                    null, failures.get(0));
     }
   }
+  
+  class FailureRecordingConcurrentUpdateSolrClient extends ConcurrentUpdateSolrClient {
+    private final List<Throwable> failures = new ArrayList<>();
+    
+    public FailureRecordingConcurrentUpdateSolrClient(String serverUrl, int queueSize, int numThreads) {
+      super(serverUrl, null, queueSize, numThreads, null, false);
+    }
+    
+    @Override
+    public void handleError(Throwable ex) {
+      failures.add(ex);
+    }
+  }
 
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
index ad20e95..11d2784 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/BasicHttpSolrClientTest.java
@@ -16,6 +16,10 @@
  */
 package org.apache.solr.client.solrj.impl;
 
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
 import java.io.InputStream;
 import java.lang.invoke.MethodHandles;
@@ -31,11 +35,6 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
 import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpException;
@@ -209,7 +208,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   public void testTimeout() throws Exception {
 
     SolrQuery q = new SolrQuery("*:*");
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/slow/foo")) {
+    try(HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString() + "/slow/foo")) {
       client.setSoTimeout(2000);
       client.query(q, METHOD.GET);
       fail("No exception thrown.");
@@ -229,7 +228,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
     assertEquals(status + " didn't generate an UNKNOWN error code, someone modified the list of valid ErrorCode's w/o changing this test to work a different way",
         ErrorCode.UNKNOWN, ErrorCode.getErrorCode(status));
 
-    try ( HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+    try (HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
       DebugServlet.setErrorCode(status);
       try {
         SolrQuery q = new SolrQuery("foo");
@@ -246,7 +245,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   @Test
   public void testQuery() throws Exception {
     DebugServlet.clear();
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+    try (HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
       SolrQuery q = new SolrQuery("foo");
       q.setParam("a", "\u1234");
       try {
@@ -370,7 +369,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   @Test
   public void testDelete() throws Exception {
     DebugServlet.clear();
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+    try (HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
       try {
         client.deleteById("id");
       } catch (ParseException ignored) {}
@@ -411,7 +410,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   @Test
   public void testGetById() throws Exception {
     DebugServlet.clear();
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+    try (HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
       Collection<String> ids = Collections.singletonList("a");
       try {
         client.getById("a");
@@ -434,7 +433,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   @Test
   public void testUpdate() throws Exception {
     DebugServlet.clear();
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+    try (HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
       UpdateRequest req = new UpdateRequest();
       req.add(new SolrInputDocument());
       req.setParam("a", "\u1234");
@@ -498,7 +497,8 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   
   @Test
   public void testRedirect() throws Exception {
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/redirect/foo")) {
+    final String clientUrl = jetty.getBaseUrl().toString() + "/redirect/foo";
+    try (HttpSolrClient client = getHttpSolrClient(clientUrl)) {
       SolrQuery q = new SolrQuery("*:*");
       // default = false
       try {
@@ -527,7 +527,8 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   public void testCompression() throws Exception {
     SolrQuery q = new SolrQuery("*:*");
     
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+    final String clientUrl = jetty.getBaseUrl().toString() + "/debug/foo";
+    try (HttpSolrClient client = getHttpSolrClient(clientUrl)) {
       // verify request header gets set
       DebugServlet.clear();
       try {
@@ -536,14 +537,14 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
       assertNull(DebugServlet.headers.toString(), DebugServlet.headers.get("Accept-Encoding")); 
     }
     
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo", null, null, true)) {
+    try (HttpSolrClient client = getHttpSolrClient(clientUrl, null, null, true)) {
       try {
         client.query(q);
       } catch (ParseException ignored) {}
       assertNotNull(DebugServlet.headers.get("Accept-Encoding"));
     }
     
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo", null, null, false)) {
+    try (HttpSolrClient client = getHttpSolrClient(clientUrl, null, null, false)) {
       try {
         client.query(q);
       } catch (ParseException ignored) {}
@@ -577,7 +578,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
     }
     
     // verify compressed response can be handled
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/collection1")) {
+    try (HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString() + "/collection1")) {
       q = new SolrQuery("foo");
       QueryResponse response = client.query(q);
       assertEquals(0, response.getStatus());
@@ -587,7 +588,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   @Test
   public void testCollectionParameters() throws IOException, SolrServerException {
 
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString())) {
+    try (HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString())) {
       SolrInputDocument doc = new SolrInputDocument();
       doc.addField("id", "collection");
       client.add("collection1", doc);
@@ -596,7 +597,8 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
       assertEquals(1, client.query("collection1", new SolrQuery("id:collection")).getResults().getNumFound());
     }
 
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/collection1")) {
+    final String collection1Url = jetty.getBaseUrl().toString() + "/collection1";
+    try (HttpSolrClient client = getHttpSolrClient(collection1Url)) {
       assertEquals(1, client.query(new SolrQuery("id:collection")).getResults().getNumFound());
     }
 
@@ -606,7 +608,7 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   public void testGetRawStream() throws SolrServerException, IOException{
     CloseableHttpClient client = HttpClientUtil.createClient(null);
     try {
-      HttpSolrClient solrClient = new HttpSolrClient(jetty.getBaseUrl().toString() + "/collection1",
+      HttpSolrClient solrClient = getHttpSolrClient(jetty.getBaseUrl().toString() + "/collection1",
           client, null);
       QueryRequest req = new QueryRequest();
       NamedList response = solrClient.request(req);
@@ -693,8 +695,8 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
     HttpClientUtil.addRequestInterceptor(changeRequestInterceptor);
     HttpClientUtil.addRequestInterceptor(cookieSettingRequestInterceptor);    
 
-    try(HttpSolrClient server = new HttpSolrClient(jetty.getBaseUrl().toString() +
-        "/debug/foo")) {
+    final String clientUrl = jetty.getBaseUrl().toString() + "/debug/foo";
+    try(HttpSolrClient server = getHttpSolrClient(clientUrl)) {
 
       SolrQuery q = new SolrQuery("foo");
       q.setParam("a", "\u1234");
@@ -765,7 +767,8 @@ public class BasicHttpSolrClientTest extends SolrJettyTestBase {
   @Test
   public void testQueryString() throws Exception {
 
-    try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString() + "/debug/foo")) {
+    final String clientUrl = jetty.getBaseUrl().toString() + "/debug/foo";
+    try(HttpSolrClient client = getHttpSolrClient(clientUrl)) {
       // test without request query params
       DebugServlet.clear();
       client.setQueryParams(setOf("serverOnly"));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientBuilderTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientBuilderTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientBuilderTest.java
new file mode 100644
index 0000000..57692c7
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientBuilderTest.java
@@ -0,0 +1,90 @@
+package org.apache.solr.client.solrj.impl;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
+import org.junit.Test;
+
+/*
+ * 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.
+ */
+
+public class CloudSolrClientBuilderTest extends LuceneTestCase {
+  private static final String ANY_CHROOT = "/ANY_CHROOT";
+  private static final String ANY_ZK_HOST = "ANY_ZK_HOST";
+  private static final String ANY_OTHER_ZK_HOST = "ANY_OTHER_ZK_HOST";
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testNoZkHostSpecified() {
+    new Builder()
+      .withZkChroot(ANY_CHROOT)
+      .build();
+  }
+  
+  @Test
+  public void testSingleZkHostSpecified() throws IOException {
+    try(CloudSolrClient createdClient = new Builder()
+        .withZkHost(ANY_ZK_HOST)
+        .withZkChroot(ANY_CHROOT)
+        .build()) {
+      final String clientZkHost = createdClient.getZkHost();
+    
+      assertTrue(clientZkHost.contains(ANY_ZK_HOST));
+    }
+  }
+  
+  @Test
+  public void testSeveralZkHostsSpecifiedSingly() throws IOException {
+    try (CloudSolrClient createdClient = new Builder()
+        .withZkHost(ANY_ZK_HOST)
+        .withZkHost(ANY_OTHER_ZK_HOST)
+        .withZkChroot(ANY_CHROOT)
+        .build()) {
+      final String clientZkHost = createdClient.getZkHost();
+    
+      assertTrue(clientZkHost.contains(ANY_ZK_HOST));
+      assertTrue(clientZkHost.contains(ANY_OTHER_ZK_HOST));
+    }
+  }
+  
+  @Test
+  public void testSeveralZkHostsSpecifiedTogether() throws IOException {
+    final ArrayList<String> zkHosts = new ArrayList<String>();
+    zkHosts.add(ANY_ZK_HOST);
+    zkHosts.add(ANY_OTHER_ZK_HOST);
+    try(CloudSolrClient createdClient = new Builder()
+        .withZkHost(zkHosts)
+        .withZkChroot(ANY_CHROOT)
+        .build()) {
+      final String clientZkHost = createdClient.getZkHost();
+    
+      assertTrue(clientZkHost.contains(ANY_ZK_HOST));
+      assertTrue(clientZkHost.contains(ANY_OTHER_ZK_HOST));
+    }
+  }
+  
+  @Test
+  public void testByDefaultConfiguresClientToSendUpdatesOnlyToShardLeaders() throws IOException {
+    try(CloudSolrClient createdClient = new Builder()
+        .withZkHost(ANY_ZK_HOST)
+        .withZkChroot(ANY_CHROOT)
+        .build()) {
+      assertTrue(createdClient.isUpdatesToLeaders() == true);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
index 8c50e8e..5864389 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientTest.java
@@ -225,7 +225,7 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
       params.add("q", "id:" + id);
       params.add("distrib", "false");
       QueryRequest queryRequest = new QueryRequest(params);
-      try (HttpSolrClient solrClient = new HttpSolrClient(url)) {
+      try (HttpSolrClient solrClient = getHttpSolrClient(url)) {
         QueryResponse queryResponse = queryRequest.process(solrClient);
         SolrDocumentList docList = queryResponse.getResults();
         assertTrue(docList.getNumFound() == 1);
@@ -247,7 +247,7 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
     assertTrue(docs.getNumFound() == 0);
     
     // Test Multi-Threaded routed updates for UpdateRequest
-    try (CloudSolrClient threadedClient = new CloudSolrClient(zkServer.getZkAddress())) {
+    try (CloudSolrClient threadedClient = getCloudSolrClient(zkServer.getZkAddress())) {
       threadedClient.setParallelUpdates(true);
       threadedClient.setDefaultCollection(collectionName);
       response = threadedClient.request(request);
@@ -266,7 +266,7 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
         params.add("q", "id:" + id);
         params.add("distrib", "false");
         QueryRequest queryRequest = new QueryRequest(params);
-        try (HttpSolrClient solrClient = new HttpSolrClient(url)) {
+        try (HttpSolrClient solrClient = getHttpSolrClient(url)) {
           QueryResponse queryResponse = queryRequest.process(solrClient);
           SolrDocumentList docList = queryResponse.getResults();
           assertTrue(docList.getNumFound() == 1);
@@ -480,7 +480,7 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
       SolrServerException, IOException {
 
     NamedList<Object> resp;
-    try (HttpSolrClient client = new HttpSolrClient(baseUrl + "/"+ collectionName)) {
+    try (HttpSolrClient client = getHttpSolrClient(baseUrl + "/"+ collectionName)) {
       client.setConnectionTimeout(15000);
       client.setSoTimeout(60000);
       ModifiableSolrParams params = new ModifiableSolrParams();
@@ -552,7 +552,8 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
       SolrQuery q = new SolrQuery().setQuery("*:*");
       HttpSolrClient.RemoteSolrException sse = null;
 
-      try (HttpSolrClient solrClient = new HttpSolrClient(r.getStr(ZkStateReader.BASE_URL_PROP) + "/"+collectionName)) {
+      final String url = r.getStr(ZkStateReader.BASE_URL_PROP) + "/" +collectionName;
+      try (HttpSolrClient solrClient = getHttpSolrClient(url)) {
 
         log.info("should work query, result {}", solrClient.query(q));
         //no problem
@@ -588,7 +589,9 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
       log.info("the node which does not serve this collection{} ",theNode);
       assertNotNull(theNode);
 
-      try (SolrClient solrClient = new HttpSolrClient(theNode + "/"+collectionName)) {
+      
+      final String solrClientUrl = theNode + "/" + collectionName;
+      try (SolrClient solrClient = getHttpSolrClient(solrClientUrl)) {
 
         q.setParam(CloudSolrClient.STATE_VERSION, collectionName + ":" + (coll.getZNodeVersion()-1));
         try {
@@ -605,7 +608,7 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
   }
 
   public void testShutdown() throws IOException {
-    try (CloudSolrClient client = new CloudSolrClient("[ff01::114]:33332")) {
+    try (CloudSolrClient client = getCloudSolrClient("[ff01::114]:33332")) {
       client.setZkConnectTimeout(100);
       client.connect();
       fail("Expected exception");
@@ -622,7 +625,7 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
     exception.expect(SolrException.class);
     exception.expectMessage("cluster not found/not ready");
 
-    try (CloudSolrClient client = new CloudSolrClient(zkServer.getZkAddress() + "/xyz/foo")) {
+    try (CloudSolrClient client = getCloudSolrClient(zkServer.getZkAddress() + "/xyz/foo")) {
       client.setDefaultCollection(DEFAULT_COLLECTION);
       client.setZkClientTimeout(1000 * 60);
       client.connect();
@@ -632,7 +635,7 @@ public class CloudSolrClientTest extends AbstractFullDistribZkTestBase {
 
   public void customHttpClientTest() throws IOException {
     CloseableHttpClient client = HttpClientUtil.createClient(null);
-    try (CloudSolrClient solrClient = new CloudSolrClient(zkServer.getZkAddress(), client)) {
+    try (CloudSolrClient solrClient = getCloudSolrClient(zkServer.getZkAddress(), client)) {
 
       assertTrue(solrClient.getLbClient().getHttpClient() == client);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBuilderTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBuilderTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBuilderTest.java
new file mode 100644
index 0000000..3389b7f
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientBuilderTest.java
@@ -0,0 +1,33 @@
+package org.apache.solr.client.solrj.impl;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient.Builder;
+import org.junit.Test;
+
+/*
+ * 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.
+ */
+
+/**
+ * Unit tests for {@link Builder}.
+ */
+public class ConcurrentUpdateSolrClientBuilderTest extends LuceneTestCase {
+
+  @Test(expected = IllegalArgumentException.class)
+  public void testRejectsMissingBaseSolrUrl() {
+    new Builder(null).build();
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java
index bd5e6a2..5e2baeb 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClientTest.java
@@ -147,17 +147,8 @@ public class ConcurrentUpdateSolrClientTest extends SolrJettyTestBase {
     final StringBuilder errors = new StringBuilder();     
     
     @SuppressWarnings("serial")
-    ConcurrentUpdateSolrClient concurrentClient = new ConcurrentUpdateSolrClient(serverUrl, cussQueueSize, cussThreadCount) {
-      @Override
-      public void handleError(Throwable ex) {
-        errorCounter.incrementAndGet();
-        errors.append(" "+ex);
-      }
-      @Override
-      public void onSuccess(HttpResponse resp) {
-        successCounter.incrementAndGet();
-      }
-    };
+    ConcurrentUpdateSolrClient concurrentClient = new OutcomeCountingConcurrentUpdateSolrClient(serverUrl, cussQueueSize,
+        cussThreadCount, successCounter, errorCounter, errors);
     
     concurrentClient.setPollQueueTime(0);
     
@@ -224,4 +215,28 @@ public class ConcurrentUpdateSolrClientTest extends SolrJettyTestBase {
       }      
     }    
   }
+  
+  class OutcomeCountingConcurrentUpdateSolrClient extends ConcurrentUpdateSolrClient {
+    private final AtomicInteger successCounter;
+    private final AtomicInteger failureCounter;
+    private final StringBuilder errors;
+    public OutcomeCountingConcurrentUpdateSolrClient(String serverUrl, int queueSize, int threadCount,
+        AtomicInteger successCounter, AtomicInteger failureCounter, StringBuilder errors) {
+      super(serverUrl, null, queueSize, threadCount, null, false);
+      
+      this.successCounter = successCounter;
+      this.failureCounter = failureCounter;
+      this.errors = errors;
+    }
+    
+    @Override
+    public void handleError(Throwable ex) {
+      failureCounter.incrementAndGet();
+      errors.append(" "+ex);
+    }
+    @Override
+    public void onSuccess(HttpResponse resp) {
+      successCounter.incrementAndGet();
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBuilderTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBuilderTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBuilderTest.java
new file mode 100644
index 0000000..da56576
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/HttpSolrClientBuilderTest.java
@@ -0,0 +1,76 @@
+package org.apache.solr.client.solrj.impl;
+
+import java.io.IOException;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.solr.client.solrj.ResponseParser;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
+import org.junit.Test;
+
+/*
+ * 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.
+ */
+
+/**
+ * Unit tests for {@link Builder}.
+ */
+public class HttpSolrClientBuilderTest extends LuceneTestCase {
+  private static final String ANY_BASE_SOLR_URL = "ANY_BASE_SOLR_URL";
+  private static final HttpClient ANY_HTTP_CLIENT = HttpClientBuilder.create().build();
+  private static final ResponseParser ANY_RESPONSE_PARSER = new NoOpResponseParser();
+  
+  @Test(expected = IllegalArgumentException.class)
+  public void testBaseSolrUrlIsRequired() {
+    new Builder(null)
+        .build();
+  }
+
+  @Test
+  public void testProvidesBaseSolrUrlToClient() throws IOException {
+    try (HttpSolrClient createdClient = new HttpSolrClient.Builder(ANY_BASE_SOLR_URL).build()) {
+      assertTrue(createdClient.getBaseURL().equals(ANY_BASE_SOLR_URL));
+    }
+  }
+  
+  @Test
+  public void testProvidesHttpClientToClient() throws IOException {
+    try(HttpSolrClient createdClient = new Builder(ANY_BASE_SOLR_URL)
+        .withHttpClient(ANY_HTTP_CLIENT)
+        .build()) {
+      assertTrue(createdClient.getHttpClient().equals(ANY_HTTP_CLIENT));
+    }
+  }
+  
+  @Test
+  public void testProvidesResponseParserToClient() throws IOException {
+    try(HttpSolrClient createdClient = new Builder(ANY_BASE_SOLR_URL)
+        .withResponseParser(ANY_RESPONSE_PARSER)
+        .build()) {
+      assertTrue(createdClient.getParser().equals(ANY_RESPONSE_PARSER));
+    }
+  }
+  
+  @Test
+  public void testDefaultsToBinaryResponseParserWhenNoneProvided() throws IOException {
+    try(HttpSolrClient createdClient = new Builder(ANY_BASE_SOLR_URL)
+        .build()) {
+      final ResponseParser usedParser = createdClient.getParser();
+      assertTrue(usedParser instanceof BinaryResponseParser);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBuilderTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBuilderTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBuilderTest.java
new file mode 100644
index 0000000..6a02da5
--- /dev/null
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/LBHttpSolrClientBuilderTest.java
@@ -0,0 +1,65 @@
+package org.apache.solr.client.solrj.impl;
+
+import org.apache.http.client.HttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.solr.client.solrj.impl.LBHttpSolrClient.Builder;
+import org.apache.solr.client.solrj.ResponseParser;
+import org.junit.Test;
+
+/*
+ * 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.
+ */
+
+/**
+ * Unit tests for {@link Builder}.
+ */
+public class LBHttpSolrClientBuilderTest extends LuceneTestCase {
+  private static final String ANY_BASE_SOLR_URL = "ANY_BASE_SOLR_URL";
+  private static final HttpClient ANY_HTTP_CLIENT = HttpClientBuilder.create().build();
+  private static final ResponseParser ANY_RESPONSE_PARSER = new NoOpResponseParser();
+
+  @Test
+  public void providesHttpClientToClient() {
+    try(LBHttpSolrClient createdClient = new Builder()
+        .withBaseSolrUrl(ANY_BASE_SOLR_URL)
+        .withHttpClient(ANY_HTTP_CLIENT)
+        .build()) {
+      assertTrue(createdClient.getHttpClient().equals(ANY_HTTP_CLIENT));
+    }
+  }
+  
+  @Test
+  public void providesResponseParserToClient() {
+    try(LBHttpSolrClient createdClient = new Builder()
+        .withBaseSolrUrl(ANY_BASE_SOLR_URL)
+        .withResponseParser(ANY_RESPONSE_PARSER)
+        .build()) {
+      assertTrue(createdClient.getParser().equals(ANY_RESPONSE_PARSER));
+    }
+  }
+  
+  @Test
+  public void testDefaultsToBinaryResponseParserWhenNoneProvided() {
+    try(LBHttpSolrClient createdClient = new Builder()
+        .withBaseSolrUrl(ANY_BASE_SOLR_URL)
+        .build()) {
+      final ResponseParser usedParser = createdClient.getParser();
+    
+      assertTrue(usedParser instanceof BinaryResponseParser);
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
index 4ae46f8..8c6eb60 100644
--- a/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
+++ b/solr/test-framework/src/java/org/apache/solr/BaseDistributedSearchTestCase.java
@@ -439,7 +439,7 @@ public abstract class BaseDistributedSearchTestCase extends SolrTestCaseJ4 {
   protected SolrClient createNewSolrClient(int port) {
     try {
       // setup the client...
-      HttpSolrClient client = new HttpSolrClient(buildUrl(port) + "/" + DEFAULT_TEST_CORENAME);
+      HttpSolrClient client = getHttpSolrClient(buildUrl(port) + "/" + DEFAULT_TEST_CORENAME);
       return client;
     }
     catch (Exception ex) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java b/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java
index 5924593..0badec1 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrJettyTestBase.java
@@ -154,7 +154,7 @@ abstract public class SolrJettyTestBase extends SolrTestCaseJ4
       try {
         // setup the client...
         String url = jetty.getBaseUrl().toString() + "/" + "collection1";
-        HttpSolrClient client = new HttpSolrClient( url );
+        HttpSolrClient client = getHttpSolrClient(url);
         client.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
         return client;
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
index 4aed135..118c194 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseHS.java
@@ -16,15 +16,31 @@
  */
 package org.apache.solr;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.invoke.MethodHandles;
+import java.nio.file.Files;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Random;
+import java.util.Set;
+
 import com.google.common.base.Charsets;
 import org.apache.commons.io.FileUtils;
 import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.embedded.JettyConfig;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
-import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.impl.NoOpResponseParser;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -43,24 +59,6 @@ import org.noggit.ObjectBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.File;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-import java.lang.invoke.MethodHandles;
-import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Random;
-import java.util.Set;
-
 
 @SolrTestCaseJ4.SuppressSSL
 //@LuceneTestCase.SuppressCodecs({"Lucene3x","Lucene40","Lucene41","Lucene42","Lucene45","Appending","Asserting"})
@@ -418,7 +416,7 @@ public class SolrTestCaseHS extends SolrTestCaseJ4 {
 
     public SolrClient getSolrJ() {
       if (solrj == null) {
-        solrj = new HttpSolrClient(getCollectionURL());
+        solrj = getHttpSolrClient(getCollectionURL());
       }
       return solrj;
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
index 6b28eb8..28e5879 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -31,6 +31,7 @@ import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.lang.annotation.Target;
 import java.lang.invoke.MethodHandles;
+import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.charset.Charset;
 import java.nio.charset.StandardCharsets;
@@ -56,6 +57,7 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
 import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;
 import org.apache.commons.codec.Charsets;
 import org.apache.commons.io.FileUtils;
+import org.apache.http.client.HttpClient;
 import org.apache.lucene.analysis.MockAnalyzer;
 import org.apache.lucene.analysis.MockTokenizer;
 import org.apache.lucene.index.IndexWriterConfig;
@@ -66,7 +68,13 @@ import org.apache.lucene.util.LuceneTestCase.SuppressSysoutChecks;
 import org.apache.lucene.util.QuickPatchThreadsFilter;
 import org.apache.lucene.util.TestUtil;
 import org.apache.solr.client.solrj.embedded.JettyConfig;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
+import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
+import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
+import org.apache.solr.client.solrj.ResponseParser;
 import org.apache.solr.client.solrj.util.ClientUtils;
 import org.apache.solr.cloud.IpTables;
 import org.apache.solr.common.SolrDocument;
@@ -2037,6 +2045,140 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
   public static Object skewed(Object likely, Object unlikely) {
     return (0 == TestUtil.nextInt(random(), 0, 9)) ? unlikely : likely;
   }
+  
+  public static CloudSolrClient getCloudSolrClient(String zkHost) {
+    if (random().nextBoolean()) {
+      return new CloudSolrClient(zkHost);
+    }
+    return new CloudSolrClient.Builder()
+        .withZkHost(zkHost)
+        .build();
+  }
+  
+  public static CloudSolrClient getCloudSolrClient(String zkHost, HttpClient httpClient) {
+    if (random().nextBoolean()) {
+      return new CloudSolrClient(zkHost, httpClient);
+    }
+    return new CloudSolrClient.Builder()
+        .withZkHost(zkHost)
+        .withHttpClient(httpClient)
+        .build();
+  }
+  
+  public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly) {
+    if (random().nextBoolean()) {
+      return new CloudSolrClient(zkHost, shardLeadersOnly);
+    }
+    
+    if (shardLeadersOnly) {
+      return new CloudSolrClient.Builder()
+          .withZkHost(zkHost)
+          .sendUpdatesOnlyToShardLeaders()
+          .build();
+    }
+    return new CloudSolrClient.Builder()
+        .withZkHost(zkHost)
+        .sendUpdatesToAllReplicasInShard()
+        .build();
+  }
+  
+  public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, HttpClient httpClient) {
+    if (random().nextBoolean()) {
+      return new CloudSolrClient(zkHost, shardLeadersOnly, httpClient);
+    }
+    
+    if (shardLeadersOnly) {
+      return new CloudSolrClient.Builder()
+          .withZkHost(zkHost)
+          .withHttpClient(httpClient)
+          .sendUpdatesOnlyToShardLeaders()
+          .build();
+    }
+    return new CloudSolrClient.Builder()
+        .withZkHost(zkHost)
+        .withHttpClient(httpClient)
+        .sendUpdatesToAllReplicasInShard()
+        .build();
+  }
+  
+  public static ConcurrentUpdateSolrClient getConcurrentUpdateSolrClient(String baseSolrUrl, int queueSize, int threadCount) {
+    if (random().nextBoolean()) {
+      return new ConcurrentUpdateSolrClient(baseSolrUrl, queueSize, threadCount);
+    }
+    return new ConcurrentUpdateSolrClient.Builder(baseSolrUrl)
+        .withQueueSize(queueSize)
+        .withThreadCount(threadCount)
+        .build();
+  }
+  
+  public static ConcurrentUpdateSolrClient getConcurrentUpdateSolrClient(String baseSolrUrl, HttpClient httpClient, int queueSize, int threadCount) {
+    if (random().nextBoolean()) {
+      return new ConcurrentUpdateSolrClient(baseSolrUrl, httpClient, queueSize, threadCount);
+    }
+    return new ConcurrentUpdateSolrClient.Builder(baseSolrUrl)
+        .withHttpClient(httpClient)
+        .withQueueSize(queueSize)
+        .withThreadCount(threadCount)
+        .build();
+  }
+  
+  public static LBHttpSolrClient getLBHttpSolrClient(HttpClient client, String... solrUrls) {
+    if (random().nextBoolean()) {
+      return new LBHttpSolrClient(client, solrUrls);
+    }
+    
+    return new LBHttpSolrClient.Builder()
+        .withHttpClient(client)
+        .withBaseSolrUrls(solrUrls)
+        .build();
+  }
+  
+  public static LBHttpSolrClient getLBHttpSolrClient(String... solrUrls) throws MalformedURLException {
+    if (random().nextBoolean()) {
+      return new LBHttpSolrClient(solrUrls);
+    }
+    return new LBHttpSolrClient.Builder()
+        .withBaseSolrUrls(solrUrls)
+        .build();
+  }
+  
+  public static HttpSolrClient getHttpSolrClient(String url, HttpClient httpClient, ResponseParser responseParser, boolean compression) {
+    if(random().nextBoolean()) {
+      return new HttpSolrClient(url, httpClient, responseParser, compression);
+    }
+    return new Builder(url)
+        .withHttpClient(httpClient)
+        .withResponseParser(responseParser)
+        .allowCompression(compression)
+        .build();
+  }
+  
+  public static HttpSolrClient getHttpSolrClient(String url, HttpClient httpClient, ResponseParser responseParser) {
+    if(random().nextBoolean()) {
+      return new HttpSolrClient(url, httpClient, responseParser);
+    }
+    return new Builder(url)
+        .withHttpClient(httpClient)
+        .withResponseParser(responseParser)
+        .build();
+  }
+  
+  public static HttpSolrClient getHttpSolrClient(String url, HttpClient httpClient) {
+    if(random().nextBoolean()) {
+      return new HttpSolrClient(url, httpClient);
+    }
+    return new Builder(url)
+        .withHttpClient(httpClient)
+        .build();
+  }
+
+  public static HttpSolrClient getHttpSolrClient(String url) {
+    if(random().nextBoolean()) {
+      return new HttpSolrClient(url);
+    }
+    return new Builder(url)
+        .build();
+  }
 
   /** 
    * Returns a randomly generated Date in the appropriate Solr external (input) format 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
index 090dfe8..a4a4172 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractFullDistribZkTestBase.java
@@ -16,11 +16,6 @@
  */
 package org.apache.solr.cloud;
 
-import static org.apache.solr.cloud.OverseerCollectionMessageHandler.CREATE_NODE_SET;
-import static org.apache.solr.cloud.OverseerCollectionMessageHandler.NUM_SLICES;
-import static org.apache.solr.cloud.OverseerCollectionMessageHandler.SHARDS_PROP;
-import static org.apache.solr.common.util.Utils.makeMap;
-
 import java.io.File;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
@@ -90,6 +85,11 @@ import org.noggit.JSONWriter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.solr.cloud.OverseerCollectionMessageHandler.CREATE_NODE_SET;
+import static org.apache.solr.cloud.OverseerCollectionMessageHandler.NUM_SLICES;
+import static org.apache.solr.cloud.OverseerCollectionMessageHandler.SHARDS_PROP;
+import static org.apache.solr.common.util.Utils.makeMap;
+
 /**
  * TODO: we should still test this works as a custom update chain as well as
  * what we test now - the default update chain
@@ -272,7 +272,7 @@ public abstract class AbstractFullDistribZkTestBase extends AbstractDistribZkTes
   }
   
   protected CloudSolrClient createCloudClient(String defaultCollection) {
-    CloudSolrClient client = new CloudSolrClient(zkServer.getZkAddress(), random().nextBoolean());
+    CloudSolrClient client = getCloudSolrClient(zkServer.getZkAddress(), random().nextBoolean());
     client.setParallelUpdates(random().nextBoolean());
     if (defaultCollection != null) client.setDefaultCollection(defaultCollection);
     client.getLbClient().setConnectionTimeout(30000);
@@ -1626,7 +1626,7 @@ public abstract class AbstractFullDistribZkTestBase extends AbstractDistribZkTes
       // setup the server...
       String baseUrl = buildUrl(port);
       String url = baseUrl + (baseUrl.endsWith("/") ? "" : "/") + DEFAULT_COLLECTION;
-      HttpSolrClient client = new HttpSolrClient(url);
+      HttpSolrClient client = getHttpSolrClient(url);
       client.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
       client.setSoTimeout(60000);
       return client;
@@ -1638,7 +1638,7 @@ public abstract class AbstractFullDistribZkTestBase extends AbstractDistribZkTes
   protected SolrClient createNewSolrClient(String collection, String baseUrl) {
     try {
       // setup the server...
-      HttpSolrClient client = new HttpSolrClient(baseUrl + "/" + collection);
+      HttpSolrClient client = getHttpSolrClient(baseUrl + "/" + collection);
       client.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
       return client;
     }
@@ -1722,7 +1722,7 @@ public abstract class AbstractFullDistribZkTestBase extends AbstractDistribZkTes
       if (commonCloudSolrClient == null) {
         boolean updatesToLeaders = random().nextBoolean();
         boolean parallelUpdates = random().nextBoolean();
-        commonCloudSolrClient = new CloudSolrClient(zkServer.getZkAddress(),
+        commonCloudSolrClient = getCloudSolrClient(zkServer.getZkAddress(),
                 updatesToLeaders);
         commonCloudSolrClient.getLbClient().setConnectionTimeout(5000);
         commonCloudSolrClient.getLbClient().setSoTimeout(120000);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
----------------------------------------------------------------------
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
index 118f7be..d23b37c 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/MiniSolrCloudCluster.java
@@ -42,6 +42,7 @@ import org.apache.solr.client.solrj.embedded.JettyConfig;
 import org.apache.solr.client.solrj.embedded.JettySolrRunner;
 import org.apache.solr.client.solrj.embedded.SSLConfig;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.common.cloud.SolrZkClient;
 import org.apache.solr.common.cloud.ZkConfigManager;
@@ -445,7 +446,9 @@ public class MiniSolrCloudCluster {
   }
   
   protected CloudSolrClient buildSolrClient() {
-    return new CloudSolrClient(getZkServer().getZkAddress());
+    return new Builder()
+        .withZkHost(getZkServer().getZkAddress())
+        .build();
   }
 
   private static String getHostContextSuitableForServletContext(String ctx) {


[2/3] lucene-solr:master: SOLR-8097: Implement builder pattern design for constructing SolrJ clients and deprecate direct construction of clients

Posted by an...@apache.org.
http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java b/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java
index 959d3b2..18a5f9c 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DeleteInactiveReplicaTest.java
@@ -128,7 +128,7 @@ public class DeleteInactiveReplicaTest extends AbstractFullDistribZkTestBase{
 
       Map m = Utils.makeMap("qt", "/admin/cores", "action", "status");
 
-      try (SolrClient queryClient = new HttpSolrClient(replica1.getStr(ZkStateReader.BASE_URL_PROP))) {
+      try (SolrClient queryClient = getHttpSolrClient(replica1.getStr(ZkStateReader.BASE_URL_PROP))) {
         NamedList<Object> resp = queryClient.request(new QueryRequest(new MapSolrParams(m)));
         assertNull("The core is up and running again",
             ((NamedList) resp.get("status")).get(replica1.getStr("core")));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java b/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
index f0d6484..bb8d3be 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DeleteReplicaTest.java
@@ -97,7 +97,7 @@ public class DeleteReplicaTest extends AbstractFullDistribZkTestBase {
       if (replica1 == null) fail("no active replicas found");
 
       String dataDir = null;
-      try (HttpSolrClient replica1Client = new HttpSolrClient(replica1.getStr("base_url"))) {
+      try (HttpSolrClient replica1Client = getHttpSolrClient(replica1.getStr("base_url"))) {
         CoreAdminResponse status = CoreAdminRequest.getStatus(replica1.getStr("core"), replica1Client);
         NamedList<Object> coreStatus = status.getCoreStatus(replica1.getStr("core"));
         dataDir = (String) coreStatus.get("dataDir");
@@ -186,7 +186,7 @@ public class DeleteReplicaTest extends AbstractFullDistribZkTestBase {
     String instanceDir;
     String dataDir;
 
-    try (HttpSolrClient client = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient client = getHttpSolrClient(baseUrl)) {
       CoreAdminResponse statusResp = CoreAdminRequest.getStatus(core, client);
       NamedList r = statusResp.getCoreStatus().get(core);
       instanceDir = (String) r.findRecursive("instanceDir");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/DeleteShardTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/DeleteShardTest.java b/solr/core/src/test/org/apache/solr/cloud/DeleteShardTest.java
index 812fbe9..9097363 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DeleteShardTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DeleteShardTest.java
@@ -121,7 +121,7 @@ public class DeleteShardTest extends AbstractFullDistribZkTestBase {
         .getBaseURL();
     baseUrl = baseUrl.substring(0, baseUrl.length() - "collection1".length());
 
-    try (HttpSolrClient baseServer = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient baseServer = getHttpSolrClient(baseUrl)) {
       baseServer.setConnectionTimeout(15000);
       baseServer.setSoTimeout(60000);
       baseServer.request(request);
@@ -173,7 +173,7 @@ public class DeleteShardTest extends AbstractFullDistribZkTestBase {
     String instanceDir;
     String dataDir;
 
-    try (HttpSolrClient client = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient client = getHttpSolrClient(baseUrl)) {
       CoreAdminResponse statusResp = CoreAdminRequest.getStatus(core, client);
       NamedList r = statusResp.getCoreStatus().get(core);
       instanceDir = (String) r.findRecursive("instanceDir");
@@ -199,7 +199,7 @@ public class DeleteShardTest extends AbstractFullDistribZkTestBase {
     baseUrl = (String) leader.get("base_url");
     core = (String) leader.get("core");
 
-    try (HttpSolrClient client = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient client = getHttpSolrClient(baseUrl)) {
       CoreAdminResponse statusResp = CoreAdminRequest.getStatus(core, client);
       NamedList r = statusResp.getCoreStatus().get(core);
       instanceDir = (String) r.findRecursive("instanceDir");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java b/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
index 898f38a..812815b 100644
--- a/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/DistributedVersionInfoTest.java
@@ -105,7 +105,7 @@ public class DistributedVersionInfoTest extends AbstractFullDistribZkTestBase {
     assertEquals("leader and replica should have same max version: " + maxOnLeader, maxOnLeader, maxOnReplica);
 
     // send the same doc but with a lower version than the max in the index
-    try (SolrClient client = new HttpSolrClient(replica.getCoreUrl())) {
+    try (SolrClient client = getHttpSolrClient(replica.getCoreUrl())) {
       String docId = String.valueOf(1);
       SolrInputDocument doc = new SolrInputDocument();
       doc.setField(id, docId);
@@ -276,7 +276,7 @@ public class DistributedVersionInfoTest extends AbstractFullDistribZkTestBase {
     query.addSort(new SolrQuery.SortClause("_version_", SolrQuery.ORDER.desc));
     query.setParam("distrib", false);
 
-    try (SolrClient client = new HttpSolrClient(replica.getCoreUrl())) {
+    try (SolrClient client = getHttpSolrClient(replica.getCoreUrl())) {
       QueryResponse qr = client.query(query);
       SolrDocumentList hits = qr.getResults();
       if (hits.isEmpty())
@@ -343,7 +343,7 @@ public class DistributedVersionInfoTest extends AbstractFullDistribZkTestBase {
   }
 
   protected HttpSolrClient getHttpSolrClient(Replica replica) throws Exception {
-    return new HttpSolrClient(replica.getCoreUrl());
+    return getHttpSolrClient(replica.getCoreUrl());
   }
 
   protected void sendDoc(int docId) throws Exception {
@@ -378,7 +378,7 @@ public class DistributedVersionInfoTest extends AbstractFullDistribZkTestBase {
     ZkCoreNodeProps coreProps = new ZkCoreNodeProps(replica);
     String coreName = coreProps.getCoreName();
     boolean reloadedOk = false;
-    try (HttpSolrClient client = new HttpSolrClient(coreProps.getBaseUrl())) {
+    try (HttpSolrClient client = getHttpSolrClient(coreProps.getBaseUrl())) {
       CoreAdminResponse statusResp = CoreAdminRequest.getStatus(coreName, client);
       long leaderCoreStartTime = statusResp.getStartTime(coreName).getTime();
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java b/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java
index a71c3e6..e9e8907 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ForceLeaderTest.java
@@ -301,7 +301,7 @@ public class ForceLeaderTest extends HttpPartitionTest {
 
     SolrRequest<SimpleSolrResponse> req = new GenericSolrRequest(METHOD.GET, "/admin/cores", params);
     NamedList resp = null;
-    try (HttpSolrClient hsc = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient hsc = getHttpSolrClient(baseUrl)) {
        resp = hsc.request(req);
     }
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
index 2609914..e15ab0d 100644
--- a/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/FullSolrCloudDistribCmdsTest.java
@@ -698,7 +698,7 @@ public class FullSolrCloudDistribCmdsTest extends AbstractFullDistribZkTestBase
     QueryResponse results = query(cloudClient);
     long beforeCount = results.getResults().getNumFound();
     int cnt = TEST_NIGHTLY ? 2933 : 313;
-    try (ConcurrentUpdateSolrClient concurrentClient = new ConcurrentUpdateSolrClient(
+    try (ConcurrentUpdateSolrClient concurrentClient = getConcurrentUpdateSolrClient(
         ((HttpSolrClient) clients.get(0)).getBaseURL(), 10, 2)) {
       concurrentClient.setConnectionTimeout(120000);
       for (int i = 0; i < cnt; i++) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
index 9dcbb8c..6180fbb 100644
--- a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
@@ -590,7 +590,7 @@ public class HttpPartitionTest extends AbstractFullDistribZkTestBase {
   protected HttpSolrClient getHttpSolrClient(Replica replica, String coll) throws Exception {
     ZkCoreNodeProps zkProps = new ZkCoreNodeProps(replica);
     String url = zkProps.getBaseUrl() + "/" + coll;
-    return new HttpSolrClient(url);
+    return getHttpSolrClient(url);
   }
 
   protected int sendDoc(int docId) throws Exception {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnCommitTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnCommitTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnCommitTest.java
index 7d6c633..fd122ad 100644
--- a/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnCommitTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnCommitTest.java
@@ -163,7 +163,7 @@ public class LeaderInitiatedRecoveryOnCommitTest extends BasicDistributedZkTest
     String replicaCoreUrl = replica.getCoreUrl();
     log.info("Sending commit request to: "+replicaCoreUrl);
     final RTimer timer = new RTimer();
-    try (HttpSolrClient client = new HttpSolrClient(replicaCoreUrl)) {
+    try (HttpSolrClient client = getHttpSolrClient(replicaCoreUrl)) {
       try {
         client.commit();
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnShardRestartTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnShardRestartTest.java b/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnShardRestartTest.java
index d130f3b..928f4d6 100644
--- a/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnShardRestartTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/LeaderInitiatedRecoveryOnShardRestartTest.java
@@ -80,7 +80,7 @@ public class LeaderInitiatedRecoveryOnShardRestartTest extends AbstractFullDistr
     QueryRequest request = new QueryRequest(params);
     request.setPath("/admin/collections");
     String baseUrl = ((HttpSolrClient) clients.get(0)).getBaseURL();
-    HttpSolrClient delClient = new HttpSolrClient(baseUrl.substring(0, baseUrl.lastIndexOf("/")));
+    HttpSolrClient delClient = getHttpSolrClient(baseUrl.substring(0, baseUrl.lastIndexOf("/")));
     delClient.request(request);
     delClient.close();
     

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java b/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java
index c09e0d1..fadb880 100644
--- a/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/MigrateRouteKeyTest.java
@@ -106,7 +106,7 @@ public class MigrateRouteKeyTest extends BasicDistributedZkTest {
         .getBaseURL();
     baseUrl = baseUrl.substring(0, baseUrl.length() - "collection1".length());
 
-    try (HttpSolrClient baseClient = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient baseClient = getHttpSolrClient(baseUrl)) {
       baseClient.setConnectionTimeout(15000);
       baseClient.setSoTimeout(60000 * 5);
       baseClient.request(request);
@@ -161,7 +161,7 @@ public class MigrateRouteKeyTest extends BasicDistributedZkTest {
 
     String url = getUrlFromZk(getCommonCloudSolrClient().getZkStateReader().getClusterState(), targetCollection);
 
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
 
       SolrQuery solrQuery = new SolrQuery("*:*");
       assertEquals("DocCount on target collection does not match", 0, collectionClient.query(solrQuery).getResults().getNumFound());

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java b/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
index 894f26d..a4fbba1 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ReplicationFactorTest.java
@@ -179,7 +179,7 @@ public class ReplicationFactorTest extends AbstractFullDistribZkTestBase {
     ZkCoreNodeProps zkProps = new ZkCoreNodeProps(replica);
     String url = zkProps.getBaseUrl() + "/" + collection;
 
-    try (HttpSolrClient solrServer = new HttpSolrClient(url)) {
+    try (HttpSolrClient solrServer = getHttpSolrClient(url)) {
       NamedList resp = solrServer.request(up);
       NamedList hdr = (NamedList) resp.get("responseHeader");
       Integer batchRf = (Integer)hdr.get(UpdateRequest.REPFACT);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java b/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java
index c1b500c..8323878 100644
--- a/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/SSLMigrationTest.java
@@ -130,7 +130,7 @@ public class SSLMigrationTest extends AbstractFullDistribZkTestBase {
       urls.add(replica.getStr(ZkStateReader.BASE_URL_PROP));
     }
     //Create new SolrServer to configure new HttpClient w/ SSL config
-    new LBHttpSolrClient(urls.toArray(new String[]{})).request(request);
+    getLBHttpSolrClient(urls.toArray(new String[]{})).request(request);
   }
   
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/ShardSplitTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/ShardSplitTest.java b/solr/core/src/test/org/apache/solr/cloud/ShardSplitTest.java
index c691cf0..08e8277 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ShardSplitTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ShardSplitTest.java
@@ -16,7 +16,16 @@
  */
 package org.apache.solr.cloud;
 
-import org.apache.http.params.CoreConnectionPNames;
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
 import org.apache.lucene.util.LuceneTestCase.Slow;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
@@ -44,16 +53,6 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Random;
-import java.util.Set;
-
 import static org.apache.solr.cloud.OverseerCollectionMessageHandler.NUM_SLICES;
 import static org.apache.solr.common.cloud.ZkStateReader.MAX_SHARDS_PER_NODE;
 import static org.apache.solr.common.cloud.ZkStateReader.REPLICATION_FACTOR;
@@ -274,7 +273,7 @@ public class ShardSplitTest extends BasicDistributedZkTest {
 
     String url = getUrlFromZk(getCommonCloudSolrClient().getZkStateReader().getClusterState(), collectionName);
 
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
 
       ClusterState clusterState = cloudClient.getZkStateReader().getClusterState();
       final DocRouter router = clusterState.getCollection(collectionName).getRouter();
@@ -348,7 +347,7 @@ public class ShardSplitTest extends BasicDistributedZkTest {
 
     String url = getUrlFromZk(getCommonCloudSolrClient().getZkStateReader().getClusterState(), collectionName);
 
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
 
       String splitKey = "b!";
 
@@ -445,7 +444,7 @@ public class ShardSplitTest extends BasicDistributedZkTest {
 
     ZkCoreNodeProps shard1_0 = getLeaderUrlFromZk(AbstractDistribZkTestBase.DEFAULT_COLLECTION, SHARD1_0);
     QueryResponse response;
-    try (HttpSolrClient shard1_0Client = new HttpSolrClient(shard1_0.getCoreUrl())) {
+    try (HttpSolrClient shard1_0Client = getHttpSolrClient(shard1_0.getCoreUrl())) {
       response = shard1_0Client.query(query);
     }
     long shard10Count = response.getResults().getNumFound();
@@ -453,7 +452,7 @@ public class ShardSplitTest extends BasicDistributedZkTest {
     ZkCoreNodeProps shard1_1 = getLeaderUrlFromZk(
         AbstractDistribZkTestBase.DEFAULT_COLLECTION, SHARD1_1);
     QueryResponse response2;
-    try (HttpSolrClient shard1_1Client = new HttpSolrClient(shard1_1.getCoreUrl())) {
+    try (HttpSolrClient shard1_1Client = getHttpSolrClient(shard1_1.getCoreUrl())) {
       response2 = shard1_1Client.query(query);
     }
     long shard11Count = response2.getResults().getNumFound();
@@ -475,7 +474,7 @@ public class ShardSplitTest extends BasicDistributedZkTest {
     for (Replica replica : slice.getReplicas()) {
       String coreUrl = new ZkCoreNodeProps(replica).getCoreUrl();
       QueryResponse response;
-      try (HttpSolrClient client = new HttpSolrClient(coreUrl)) {
+      try (HttpSolrClient client = getHttpSolrClient(coreUrl)) {
         response = client.query(query);
       }
       numFound[c++] = response.getResults().getNumFound();
@@ -514,7 +513,7 @@ public class ShardSplitTest extends BasicDistributedZkTest {
         .getBaseURL();
     baseUrl = baseUrl.substring(0, baseUrl.length() - "collection1".length());
 
-    try (HttpSolrClient baseServer = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient baseServer = getHttpSolrClient(baseUrl)) {
       baseServer.setConnectionTimeout(30000);
       baseServer.setSoTimeout(60000 * 5);
       baseServer.request(request);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java b/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java
index 362009e..beda3e9 100644
--- a/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/SyncSliceTest.java
@@ -110,7 +110,7 @@ public class SyncSliceTest extends AbstractFullDistribZkTestBase {
         .getBaseURL();
     baseUrl = baseUrl.substring(0, baseUrl.length() - "collection1".length());
     
-    try (HttpSolrClient baseClient = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient baseClient = getHttpSolrClient(baseUrl)) {
       // we only set the connect timeout, not so timeout
       baseClient.setConnectionTimeout(30000);
       baseClient.request(request);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java b/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java
index 9ded40c..aad2473 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCloudDeleteByQuery.java
@@ -155,17 +155,17 @@ public class TestCloudDeleteByQuery extends SolrCloudTestCase {
       assertNotNull("could not find URL for " + shardName + " replica", passiveUrl);
 
       if (shardName.equals("shard1")) {
-        S_ONE_LEADER_CLIENT = new HttpSolrClient(leaderUrl + "/" + COLLECTION_NAME + "/");
-        S_ONE_NON_LEADER_CLIENT = new HttpSolrClient(passiveUrl + "/" + COLLECTION_NAME + "/");
+        S_ONE_LEADER_CLIENT = getHttpSolrClient(leaderUrl + "/" + COLLECTION_NAME + "/");
+        S_ONE_NON_LEADER_CLIENT = getHttpSolrClient(passiveUrl + "/" + COLLECTION_NAME + "/");
       } else if (shardName.equals("shard2")) {
-        S_TWO_LEADER_CLIENT = new HttpSolrClient(leaderUrl + "/" + COLLECTION_NAME + "/");
-        S_TWO_NON_LEADER_CLIENT = new HttpSolrClient(passiveUrl + "/" + COLLECTION_NAME + "/");
+        S_TWO_LEADER_CLIENT = getHttpSolrClient(leaderUrl + "/" + COLLECTION_NAME + "/");
+        S_TWO_NON_LEADER_CLIENT = getHttpSolrClient(passiveUrl + "/" + COLLECTION_NAME + "/");
       } else {
         fail("unexpected shard: " + shardName);
       }
     }
     assertEquals("Should be exactly one server left (nost hosting either shard)", 1, urlMap.size());
-    NO_COLLECTION_CLIENT = new HttpSolrClient(urlMap.values().iterator().next() +
+    NO_COLLECTION_CLIENT = getHttpSolrClient(urlMap.values().iterator().next() +
                                               "/" + COLLECTION_NAME + "/");
     
     assertNotNull(S_ONE_LEADER_CLIENT);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
index b505930..c804329 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
@@ -79,8 +79,8 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 {
 
   @Test
   public void testCreateErrors() throws Exception {
-    final SolrClient solrClient =
-        new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+    final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+    final SolrClient solrClient = getHttpSolrClient(baseUrl);
     final File configDir = getFile("solr").toPath().resolve("configsets/configset-2/conf").toFile();
     solrCluster.uploadConfigDir(configDir, "configSet");
 
@@ -143,8 +143,8 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 {
 
   private void verifyCreate(String baseConfigSetName, String configSetName,
       Map<String, String> oldProps, Map<String, String> newProps) throws Exception {
-    final SolrClient solrClient =
-        new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+    final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+    final SolrClient solrClient = getHttpSolrClient(baseUrl);
     setupBaseConfigSet(baseConfigSetName, oldProps);
 
     SolrZkClient zkClient = new SolrZkClient(solrCluster.getZkServer().getZkAddress(),
@@ -235,8 +235,8 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 {
 
   @Test
   public void testDeleteErrors() throws Exception {
-    final SolrClient solrClient =
-        new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+    final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+    final SolrClient solrClient = getHttpSolrClient(baseUrl);
     final File configDir = getFile("solr").toPath().resolve("configsets/configset-2/conf").toFile();
     final File tmpConfigDir = createTempDir().toFile();
     tmpConfigDir.deleteOnExit();
@@ -274,8 +274,8 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 {
 
   @Test
   public void testDelete() throws Exception {
-    final SolrClient solrClient =
-        new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+    final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+    final SolrClient solrClient = getHttpSolrClient(baseUrl);
     final File configDir = getFile("solr").toPath().resolve("configsets/configset-2/conf").toFile();
     final String configSet = "configSet";
     solrCluster.uploadConfigDir(configDir, configSet);
@@ -300,8 +300,8 @@ public class TestConfigSetsAPI extends SolrTestCaseJ4 {
 
   @Test
   public void testList() throws Exception {
-    final SolrClient solrClient =
-        new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+    final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+    final SolrClient solrClient = getHttpSolrClient(baseUrl);
 
     SolrZkClient zkClient = new SolrZkClient(solrCluster.getZkServer().getZkAddress(),
         AbstractZkTestCase.TIMEOUT, AbstractZkTestCase.TIMEOUT, null);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java
index 2d2aa58..c5a0bc5 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIExclusivity.java
@@ -121,8 +121,8 @@ public class TestConfigSetsAPIExclusivity extends SolrTestCaseJ4 {
     public abstract ConfigSetAdminRequest createRequest();
 
     public void run() {
-      final SolrClient solrClient =
-          new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+      final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+      final SolrClient solrClient = getHttpSolrClient(baseUrl);
       ConfigSetAdminRequest request = createRequest();
 
       for (int i = 0; i < trials; ++i) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java
index 9e5989a..458d68a 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPIZkFailure.java
@@ -99,8 +99,8 @@ public class TestConfigSetsAPIZkFailure extends SolrTestCaseJ4 {
 
   @Test
   public void testCreateZkFailure() throws Exception {
-    final SolrClient solrClient =
-        new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+    final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+    final SolrClient solrClient = getHttpSolrClient(baseUrl);
 
     final Map<String, String> oldProps = ImmutableMap.of("immutable", "true");
     setupBaseConfigSet(BASE_CONFIGSET_NAME, oldProps);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java b/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java
index cdbc170..a8e2063 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestCryptoKeys.java
@@ -119,7 +119,7 @@ public class TestCryptoKeys extends AbstractFullDistribZkTestBase {
     String baseURL = randomClient.getBaseURL();
     baseURL = baseURL.substring(0, baseURL.lastIndexOf('/'));
 
-    TestBlobHandler.createSystemCollection(new HttpSolrClient(baseURL, randomClient.getHttpClient()));
+    TestBlobHandler.createSystemCollection(getHttpSolrClient(baseURL, randomClient.getHttpClient()));
     waitForRecoveriesToFinish(".system", true);
 
     ByteBuffer jar = TestDynamicLoading.getFileContent("runtimecode/runtimelibs.jar.bin");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
----------------------------------------------------------------------
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 bc4352f..b82ba74 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestMiniSolrCloudClusterSSL.java
@@ -74,7 +74,7 @@ public class TestMiniSolrCloudClusterSSL extends SolrTestCaseJ4 {
   private void sendRequestToEachServer() throws Exception {
     List<JettySolrRunner> jettys = miniCluster.getJettySolrRunners();
     for (JettySolrRunner jetty : jettys) {
-      try (HttpSolrClient client = new HttpSolrClient(jetty.getBaseUrl().toString())) {
+      try (HttpSolrClient client = getHttpSolrClient(jetty.getBaseUrl().toString())) {
         CoreAdminRequest req = new CoreAdminRequest();
         req.setAction( CoreAdminAction.STATUS );
         client.request(req);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
index d0c2da4..264d429 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestRandomRequestDistribution.java
@@ -96,7 +96,7 @@ public class TestRandomRequestDistribution extends AbstractFullDistribZkTestBase
     assertEquals(1, replicas.size());
     String baseUrl = replicas.iterator().next().getStr(ZkStateReader.BASE_URL_PROP);
     if (!baseUrl.endsWith("/")) baseUrl += "/";
-    try (HttpSolrClient client = new HttpSolrClient(baseUrl + "a1x2")) {
+    try (HttpSolrClient client = getHttpSolrClient(baseUrl + "a1x2")) {
       client.setSoTimeout(5000);
       client.setConnectionTimeout(2000);
 
@@ -174,7 +174,7 @@ public class TestRandomRequestDistribution extends AbstractFullDistribZkTestBase
     if (!baseUrl.endsWith("/")) baseUrl += "/";
     String path = baseUrl + "football";
     log.info("Firing queries against path=" + path);
-    try (HttpSolrClient client = new HttpSolrClient(path)) {
+    try (HttpSolrClient client = getHttpSolrClient(path)) {
       client.setSoTimeout(5000);
       client.setConnectionTimeout(2000);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestRequestStatusCollectionAPI.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRequestStatusCollectionAPI.java b/solr/core/src/test/org/apache/solr/cloud/TestRequestStatusCollectionAPI.java
index 485558f..d8b66e9 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestRequestStatusCollectionAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestRequestStatusCollectionAPI.java
@@ -189,7 +189,7 @@ public class TestRequestStatusCollectionAPI extends BasicDistributedZkTest {
     String baseUrl = ((HttpSolrClient) shardToJetty.get(SHARD1).get(0).client.solrClient).getBaseURL();
     baseUrl = baseUrl.substring(0, baseUrl.length() - "collection1".length());
 
-    try (HttpSolrClient baseServer = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient baseServer = getHttpSolrClient(baseUrl)) {
       baseServer.setConnectionTimeout(15000);
       return baseServer.request(request);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
index 6c81673..ca15a69 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorCloud.java
@@ -162,17 +162,17 @@ public class TestTolerantUpdateProcessorCloud extends SolrCloudTestCase {
       assertNotNull("could not find URL for " + shardName + " replica", passiveUrl);
 
       if (shardName.equals("shard1")) {
-        S_ONE_LEADER_CLIENT = new HttpSolrClient(leaderUrl + "/" + COLLECTION_NAME + "/");
-        S_ONE_NON_LEADER_CLIENT = new HttpSolrClient(passiveUrl + "/" + COLLECTION_NAME + "/");
+        S_ONE_LEADER_CLIENT = getHttpSolrClient(leaderUrl + "/" + COLLECTION_NAME + "/");
+        S_ONE_NON_LEADER_CLIENT = getHttpSolrClient(passiveUrl + "/" + COLLECTION_NAME + "/");
       } else if (shardName.equals("shard2")) {
-        S_TWO_LEADER_CLIENT = new HttpSolrClient(leaderUrl + "/" + COLLECTION_NAME + "/");
-        S_TWO_NON_LEADER_CLIENT = new HttpSolrClient(passiveUrl + "/" + COLLECTION_NAME + "/");
+        S_TWO_LEADER_CLIENT = getHttpSolrClient(leaderUrl + "/" + COLLECTION_NAME + "/");
+        S_TWO_NON_LEADER_CLIENT = getHttpSolrClient(passiveUrl + "/" + COLLECTION_NAME + "/");
       } else {
         fail("unexpected shard: " + shardName);
       }
     }
     assertEquals("Should be exactly one server left (nost hosting either shard)", 1, urlMap.size());
-    NO_COLLECTION_CLIENT = new HttpSolrClient(urlMap.values().iterator().next() +
+    NO_COLLECTION_CLIENT = getHttpSolrClient(urlMap.values().iterator().next() +
                                               "/" + COLLECTION_NAME + "/");
     
     assertNotNull(S_ONE_LEADER_CLIENT);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
index 3a9680e..81d8881 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestTolerantUpdateProcessorRandomCloud.java
@@ -116,7 +116,7 @@ public class TestTolerantUpdateProcessorRandomCloud extends SolrCloudTestCase {
     
     for (JettySolrRunner jetty : cluster.getJettySolrRunners()) {
       URL jettyURL = jetty.getBaseUrl();
-      NODE_CLIENTS.add(new HttpSolrClient(jettyURL.toString() + "/" + COLLECTION_NAME + "/"));
+      NODE_CLIENTS.add(getHttpSolrClient(jettyURL.toString() + "/" + COLLECTION_NAME + "/"));
     }
     assertEquals(numServers, NODE_CLIENTS.size());
     

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
index 7d53fee..616cd37 100644
--- a/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/UnloadDistributedZkTest.java
@@ -123,7 +123,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     SolrClient client = clients.get(0);
     String url1 = getBaseUrl(client);
 
-    try (HttpSolrClient adminClient = new HttpSolrClient(url1)) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(url1)) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(60000);
       adminClient.request(createCmd);
@@ -174,7 +174,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     // create a new collection collection
     SolrClient client = clients.get(0);
     String url1 = getBaseUrl(client);
-    try (HttpSolrClient adminClient = new HttpSolrClient(url1)) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(url1)) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(60000);
 
@@ -194,7 +194,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     
     client = clients.get(1);
     String url2 = getBaseUrl(client);
-    try (HttpSolrClient adminClient = new HttpSolrClient(url2)) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(url2)) {
 
       Create createCmd = new Create();
       createCmd.setCoreName("unloadcollection2");
@@ -213,7 +213,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     
     Random random = random();
     if (random.nextBoolean()) {
-      try (HttpSolrClient collectionClient = new HttpSolrClient(leaderProps.getCoreUrl())) {
+      try (HttpSolrClient collectionClient = getHttpSolrClient(leaderProps.getCoreUrl())) {
         // lets try and use the solrj client to index and retrieve a couple
         // documents
         SolrInputDocument doc1 = getDoc(id, 6, i1, -600, tlong, 600, t1,
@@ -232,7 +232,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     // create another replica for our collection
     client = clients.get(2);
     String url3 = getBaseUrl(client);
-    try (HttpSolrClient adminClient = new HttpSolrClient(url3)) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(url3)) {
       Create createCmd = new Create();
       createCmd.setCoreName("unloadcollection3");
       createCmd.setCollection("unloadcollection");
@@ -246,7 +246,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     // so that we start with some versions when we reload...
     DirectUpdateHandler2.commitOnClose = false;
     
-    try (HttpSolrClient addClient = new HttpSolrClient(url3 + "/unloadcollection3")) {
+    try (HttpSolrClient addClient = getHttpSolrClient(url3 + "/unloadcollection3")) {
       addClient.setConnectionTimeout(30000);
 
       // add a few docs
@@ -260,7 +260,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     //collectionClient.commit();
     
     // unload the leader
-    try (HttpSolrClient collectionClient = new HttpSolrClient(leaderProps.getBaseUrl())) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(leaderProps.getBaseUrl())) {
       collectionClient.setConnectionTimeout(15000);
       collectionClient.setSoTimeout(30000);
 
@@ -284,7 +284,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     // ensure there is a leader
     zkStateReader.getLeaderRetry("unloadcollection", "shard1", 15000);
     
-    try (HttpSolrClient addClient = new HttpSolrClient(url2 + "/unloadcollection2")) {
+    try (HttpSolrClient addClient = getHttpSolrClient(url2 + "/unloadcollection2")) {
       addClient.setConnectionTimeout(30000);
       addClient.setSoTimeout(90000);
 
@@ -299,7 +299,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     // create another replica for our collection
     client = clients.get(3);
     String url4 = getBaseUrl(client);
-    try (HttpSolrClient adminClient = new HttpSolrClient(url4)) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(url4)) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(30000);
 
@@ -314,7 +314,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     
     // unload the leader again
     leaderProps = getLeaderUrlFromZk("unloadcollection", "shard1");
-    try (HttpSolrClient collectionClient = new HttpSolrClient(leaderProps.getBaseUrl())) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(leaderProps.getBaseUrl())) {
       collectionClient.setConnectionTimeout(15000);
       collectionClient.setSoTimeout(30000);
 
@@ -338,7 +338,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
     DirectUpdateHandler2.commitOnClose = true;
     
     // bring the downed leader back as replica
-    try (HttpSolrClient adminClient = new HttpSolrClient(leaderProps.getBaseUrl())) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(leaderProps.getBaseUrl())) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(30000);
 
@@ -352,7 +352,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
 
     long found1, found3;
     
-    try (HttpSolrClient adminClient = new HttpSolrClient(url2 + "/unloadcollection")) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(url2 + "/unloadcollection")) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(30000);
       adminClient.commit();
@@ -360,7 +360,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
       q.set("distrib", false);
       found1 = adminClient.query(q).getResults().getNumFound();
     }
-    try (HttpSolrClient adminClient = new HttpSolrClient(url3 + "/unloadcollection")) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(url3 + "/unloadcollection")) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(30000);
       adminClient.commit();
@@ -369,7 +369,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
       found3 = adminClient.query(q).getResults().getNumFound();
     }
 
-    try (HttpSolrClient adminClient = new HttpSolrClient(url4 + "/unloadcollection")) {
+    try (HttpSolrClient adminClient = getHttpSolrClient(url4 + "/unloadcollection")) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(30000);
       adminClient.commit();
@@ -387,7 +387,7 @@ public class UnloadDistributedZkTest extends BasicDistributedZkTest {
   private void testUnloadLotsOfCores() throws Exception {
     SolrClient client = clients.get(2);
     String url3 = getBaseUrl(client);
-    try (final HttpSolrClient adminClient = new HttpSolrClient(url3)) {
+    try (final HttpSolrClient adminClient = getHttpSolrClient(url3)) {
       adminClient.setConnectionTimeout(15000);
       adminClient.setSoTimeout(60000);
       int cnt = atLeast(3);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java
index 5faa065..ddf6e51 100644
--- a/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/hdfs/HdfsWriteToMultipleCollectionsTest.java
@@ -97,7 +97,7 @@ public class HdfsWriteToMultipleCollectionsTest extends BasicDistributedZkTest {
     List<CloudSolrClient> cloudClients = new ArrayList<>();
     List<StoppableIndexingThread> threads = new ArrayList<>();
     for (int i = 0; i < cnt; i++) {
-      CloudSolrClient client = new CloudSolrClient(zkServer.getZkAddress());
+      CloudSolrClient client = getCloudSolrClient(zkServer.getZkAddress());
       client.setDefaultCollection(ACOLLECTION + i);
       cloudClients.add(client);
       StoppableIndexingThread indexThread = new StoppableIndexingThread(null, client, "1", true, docCount, 1, true);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java b/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java
index 601f4fe..aeb4cb7 100644
--- a/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/hdfs/StressHdfsTest.java
@@ -165,7 +165,7 @@ public class StressHdfsTest extends BasicDistributedZkTest {
     
     int i = 0;
     for (SolrClient client : clients) {
-      try (HttpSolrClient c = new HttpSolrClient(getBaseUrl(client) + "/" + DELETE_DATA_DIR_COLLECTION)) {
+      try (HttpSolrClient c = getHttpSolrClient(getBaseUrl(client) + "/" + DELETE_DATA_DIR_COLLECTION)) {
         int docCnt = random().nextInt(1000) + 1;
         for (int j = 0; j < docCnt; j++) {
           c.add(getDoc("id", i++, "txt_t", "just some random text for a doc"));

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/core/OpenCloseCoreStressTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/OpenCloseCoreStressTest.java b/solr/core/src/test/org/apache/solr/core/OpenCloseCoreStressTest.java
index 71f3ee9..e576b0c 100644
--- a/solr/core/src/test/org/apache/solr/core/OpenCloseCoreStressTest.java
+++ b/solr/core/src/test/org/apache/solr/core/OpenCloseCoreStressTest.java
@@ -148,13 +148,13 @@ public class OpenCloseCoreStressTest extends SolrTestCaseJ4 {
     // Mostly to keep annoying logging messages from being sent out all the time.
 
     for (int idx = 0; idx < indexingThreads; ++idx) {
-      HttpSolrClient client = new HttpSolrClient(url);
+      HttpSolrClient client = getHttpSolrClient(url);
       client.setConnectionTimeout(30000);
       client.setSoTimeout(60000);
       indexingClients.add(client);
     }
     for (int idx = 0; idx < queryThreads; ++idx) {
-      HttpSolrClient client = new HttpSolrClient(url);
+      HttpSolrClient client = getHttpSolrClient(url);
       client.setConnectionTimeout(30000);
       client.setSoTimeout(30000);
       queryingClients.add(client);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java b/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java
index c8b4630..63afe6c 100644
--- a/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java
+++ b/solr/core/src/test/org/apache/solr/core/TestDynamicLoading.java
@@ -112,7 +112,7 @@ public class TestDynamicLoading extends AbstractFullDistribZkTestBase {
     assertEquals(TestBlobHandler.getAsString(map), ".system collection not available", map.get("msg"));
 
 
-    TestBlobHandler.createSystemCollection(new HttpSolrClient(baseURL, randomClient.getHttpClient()));
+    TestBlobHandler.createSystemCollection(getHttpSolrClient(baseURL, randomClient.getHttpClient()));
     waitForRecoveriesToFinish(".system", true);
 
     map = TestSolrConfigHandler.getRespMap("/test1?wt=json", client);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
index 8ea8d1b..2b974cb 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandler.java
@@ -156,7 +156,8 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
   private static SolrClient createNewSolrClient(int port) {
     try {
       // setup the client...
-      HttpSolrClient client = new HttpSolrClient(buildUrl(port) + "/" + DEFAULT_TEST_CORENAME);
+      final String baseUrl = buildUrl(port) + "/" + DEFAULT_TEST_CORENAME;
+      HttpSolrClient client = getHttpSolrClient(baseUrl);
       client.setConnectionTimeout(15000);
       client.setSoTimeout(60000);
       return client;
@@ -275,7 +276,7 @@ public class TestReplicationHandler extends SolrTestCaseJ4 {
 
   private HttpSolrClient adminClient(SolrClient client) {
     String adminUrl = ((HttpSolrClient)client).getBaseURL().replace("/collection1", "");
-    return new HttpSolrClient(adminUrl);
+    return getHttpSolrClient(adminUrl);
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
index fe1a4ea..9779c78 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestReplicationHandlerBackup.java
@@ -79,7 +79,8 @@ public class TestReplicationHandlerBackup extends SolrJettyTestBase {
   private static SolrClient createNewSolrClient(int port) {
     try {
       // setup the client...
-      HttpSolrClient client = new HttpSolrClient(buildUrl(port, context) + "/" + DEFAULT_TEST_CORENAME);
+      final String baseUrl = buildUrl(port, context) + "/" + DEFAULT_TEST_CORENAME;
+      HttpSolrClient client = getHttpSolrClient(baseUrl);
       client.setConnectionTimeout(15000);
       client.setSoTimeout(60000);
       return client;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
index 0a80764..57eb2cf 100644
--- a/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
+++ b/solr/core/src/test/org/apache/solr/handler/TestRestoreCore.java
@@ -72,7 +72,8 @@ public class TestRestoreCore extends SolrJettyTestBase {
   private static SolrClient createNewSolrClient(int port) {
     try {
       // setup the client...
-      HttpSolrClient client = new HttpSolrClient(buildUrl(port, context) + "/" + DEFAULT_TEST_CORENAME);
+      final String baseUrl = buildUrl(port, context) + "/" + DEFAULT_TEST_CORENAME;
+      HttpSolrClient client = getHttpSolrClient(baseUrl);
       client.setConnectionTimeout(15000);
       client.setSoTimeout(60000);
       return client;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
index 89f4b2b..3d4a51d 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/CoreAdminHandlerTest.java
@@ -254,7 +254,7 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
     JettySolrRunner runner = new JettySolrRunner(solrHomeDirectory.getAbsolutePath(), buildJettyConfig("/solr"));
     runner.start();
 
-    try (HttpSolrClient client = new HttpSolrClient(runner.getBaseUrl() + "/corex")) {
+    try (HttpSolrClient client = getHttpSolrClient(runner.getBaseUrl() + "/corex")) {
       client.setConnectionTimeout(SolrTestCaseJ4.DEFAULT_CONNECTION_TIMEOUT);
       client.setSoTimeout(SolrTestCaseJ4.DEFAULT_CONNECTION_TIMEOUT);
       SolrInputDocument doc = new SolrInputDocument();
@@ -263,7 +263,7 @@ public class CoreAdminHandlerTest extends SolrTestCaseJ4 {
       client.commit();
     }
 
-    try (HttpSolrClient client = new HttpSolrClient(runner.getBaseUrl().toString())) {
+    try (HttpSolrClient client = getHttpSolrClient(runner.getBaseUrl().toString())) {
       client.setConnectionTimeout(SolrTestCaseJ4.DEFAULT_CONNECTION_TIMEOUT);
       client.setSoTimeout(SolrTestCaseJ4.DEFAULT_CONNECTION_TIMEOUT);
       CoreAdminRequest.Unload req = new CoreAdminRequest.Unload(false);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java
index 16a3e87..b447668 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedDebugComponentTest.java
@@ -67,8 +67,8 @@ public class DistributedDebugComponentTest extends SolrJettyTestBase {
     createJetty(solrHome.getAbsolutePath());
     String url = jetty.getBaseUrl().toString();
 
-    collection1 = new HttpSolrClient(url + "/collection1");
-    collection2 = new HttpSolrClient(url + "/collection2");
+    collection1 = getHttpSolrClient(url + "/collection1");
+    collection2 = getHttpSolrClient(url + "/collection2");
     
     String urlCollection1 = jetty.getBaseUrl().toString() + "/" + "collection1";
     String urlCollection2 = jetty.getBaseUrl().toString() + "/" + "collection2";
@@ -76,7 +76,7 @@ public class DistributedDebugComponentTest extends SolrJettyTestBase {
     shard2 = urlCollection2.replaceAll("https?://", "");
     
     //create second core
-    try (HttpSolrClient nodeClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient nodeClient = getHttpSolrClient(url)) {
       CoreAdminRequest.Create req = new CoreAdminRequest.Create();
       req.setCoreName("collection2");
       req.setConfigSet("collection1");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java b/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java
index 91f39dc..fb90e83 100644
--- a/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/component/DistributedQueryElevationComponentTest.java
@@ -109,7 +109,8 @@ public class DistributedQueryElevationComponentTest extends BaseDistributedSearc
     assertEquals(true, document.getFieldValue("[elevated]"));
 
     // Force javabin format
-    HttpSolrClient client = new HttpSolrClient(((HttpSolrClient)clients.get(0)).getBaseURL());
+    final String clientUrl = ((HttpSolrClient)clients.get(0)).getBaseURL();
+    HttpSolrClient client = getHttpSolrClient(clientUrl);
     client.setParser(new BinaryResponseParser());
     SolrQuery solrQuery = new SolrQuery("XXXX").setParam("qt", "/elevate").setParam("shards.qt", "/elevate").setRows(500).setFields("id,[elevated]")
         .setParam("enableElevation", "true").setParam("forceElevation", "true").setParam("elevateIds", "6", "wt", "javabin")

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/search/TestSolrJ.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/TestSolrJ.java b/solr/core/src/test/org/apache/solr/search/TestSolrJ.java
index b70205e..1fd485f 100644
--- a/solr/core/src/test/org/apache/solr/search/TestSolrJ.java
+++ b/solr/core/src/test/org/apache/solr/search/TestSolrJ.java
@@ -59,7 +59,7 @@ public class TestSolrJ extends SolrTestCaseJ4 {
     ConcurrentUpdateSolrClient concurrentClient = null;
 
     // server = concurrentClient = new ConcurrentUpdateSolrServer(addr,32,8);
-    client = concurrentClient = new ConcurrentUpdateSolrClient(addr,64,nConnections);
+    client = concurrentClient = getConcurrentUpdateSolrClient(addr,64,nConnections);
 
     client.deleteByQuery("*:*");
     client.commit();
@@ -164,7 +164,7 @@ public class TestSolrJ extends SolrTestCaseJ4 {
 
   public void doCommitPerf() throws Exception {
 
-    try (HttpSolrClient client = new HttpSolrClient("http://127.0.0.1:8983/solr")) {
+    try (HttpSolrClient client = getHttpSolrClient("http://127.0.0.1:8983/solr")) {
 
       final RTimer timer = new RTimer();
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java b/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java
index 877742b..4c1c104 100644
--- a/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java
+++ b/solr/core/src/test/org/apache/solr/search/stats/TestDistribIDF.java
@@ -117,8 +117,8 @@ public class TestDistribIDF extends SolrTestCaseJ4 {
 
     //Test against all nodes
     for (JettySolrRunner jettySolrRunner : solrCluster.getJettySolrRunners()) {
-      try (SolrClient solrClient = new HttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
-        try (SolrClient solrClient_local = new HttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
+      try (SolrClient solrClient = getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
+        try (SolrClient solrClient_local = getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
 
           SolrQuery query = new SolrQuery("cat:football");
           query.setFields("*,score");
@@ -165,9 +165,9 @@ public class TestDistribIDF extends SolrTestCaseJ4 {
     //Test against all nodes
     for (JettySolrRunner jettySolrRunner : solrCluster.getJettySolrRunners()) {
 
-      try (SolrClient solrClient = new HttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
+      try (SolrClient solrClient = getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
 
-        try (SolrClient solrClient_local = new HttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
+        try (SolrClient solrClient_local = getHttpSolrClient(jettySolrRunner.getBaseUrl().toString())) {
           SolrQuery query = new SolrQuery("cat:football");
           query.setFields("*,score").add("collection", "collection1,collection2");
           QueryResponse queryResponse = solrClient.query("collection1", query);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
----------------------------------------------------------------------
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 9361615..33565dd 100644
--- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
@@ -60,6 +60,7 @@ import org.slf4j.LoggerFactory;
 
 import static java.nio.charset.StandardCharsets.UTF_8;
 import static java.util.Collections.singletonMap;
+import static org.apache.solr.SolrTestCaseJ4.getHttpSolrClient;
 import static org.apache.solr.common.cloud.ZkStateReader.BASE_URL_PROP;
 
 public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase {
@@ -166,7 +167,7 @@ public class BasicAuthIntegrationTest extends TestMiniSolrCloudClusterBase {
     CollectionAdminRequest.Reload reload = new CollectionAdminRequest.Reload();
     reload.setCollectionName(defaultCollName);
 
-    try (HttpSolrClient solrClient = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient solrClient = getHttpSolrClient(baseUrl)) {
       try {
         rsp = solrClient.request(reload);
         fail("must have failed");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/update/processor/TestNamedUpdateProcessors.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/update/processor/TestNamedUpdateProcessors.java b/solr/core/src/test/org/apache/solr/update/processor/TestNamedUpdateProcessors.java
index 85f2190..d3304f4 100644
--- a/solr/core/src/test/org/apache/solr/update/processor/TestNamedUpdateProcessors.java
+++ b/solr/core/src/test/org/apache/solr/update/processor/TestNamedUpdateProcessors.java
@@ -78,7 +78,8 @@ public class TestNamedUpdateProcessors extends AbstractFullDistribZkTestBase {
     HttpSolrClient randomClient = (HttpSolrClient) clients.get(random().nextInt(clients.size()));
     String baseURL = randomClient.getBaseURL();
 
-    TestBlobHandler.createSystemCollection(new HttpSolrClient(baseURL.substring(0, baseURL.lastIndexOf('/')), randomClient.getHttpClient()));
+    final String solrClientUrl = baseURL.substring(0, baseURL.lastIndexOf('/'));
+    TestBlobHandler.createSystemCollection(getHttpSolrClient(solrClientUrl, randomClient.getHttpClient()));
     waitForRecoveriesToFinish(".system", true);
 
     TestBlobHandler.postAndCheck(cloudClient, baseURL.substring(0, baseURL.lastIndexOf('/')), blobName, TestDynamicLoading.generateZip(RuntimeUrp.class), 1);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/util/TestSolrCLIRunExample.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/util/TestSolrCLIRunExample.java b/solr/core/src/test/org/apache/solr/util/TestSolrCLIRunExample.java
index 1a07d31..28a58ff 100644
--- a/solr/core/src/test/org/apache/solr/util/TestSolrCLIRunExample.java
+++ b/solr/core/src/test/org/apache/solr/util/TestSolrCLIRunExample.java
@@ -351,7 +351,7 @@ public class TestSolrCLIRunExample extends SolrTestCaseJ4 {
         exampleSolrHomeDir.isDirectory());
 
     if ("techproducts".equals(exampleName)) {
-      HttpSolrClient solrClient = new HttpSolrClient("http://localhost:" + bindPort + "/solr/" + exampleName);
+      HttpSolrClient solrClient = getHttpSolrClient("http://localhost:" + bindPort + "/solr/" + exampleName);
       SolrQuery query = new SolrQuery("*:*");
       QueryResponse qr = solrClient.query(query);
       long numFound = qr.getResults().getNumFound();
@@ -439,7 +439,7 @@ public class TestSolrCLIRunExample extends SolrTestCaseJ4 {
     CloudSolrClient cloudClient = null;
 
     try {
-      cloudClient = new CloudSolrClient(executor.solrCloudCluster.getZkServer().getZkAddress());
+      cloudClient = getCloudSolrClient(executor.solrCloudCluster.getZkServer().getZkAddress());
       cloudClient.connect();
       cloudClient.setDefaultCollection(collectionName);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
index aefda45..52b912c 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/CloudSolrClient.java
@@ -32,7 +32,6 @@ import java.util.List;
 import java.util.Map;
 import java.util.Random;
 import java.util.Set;
-import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
@@ -191,12 +190,17 @@ public class CloudSolrClient extends SolrClient {
    *          "host1:2181,host2:2181,host3:2181/mysolrchroot"
    *          <p>
    *          "zoo1.example.com:2181,zoo2.example.com:2181,zoo3.example.com:2181"
+   *          
+   * @deprecated use {@link Builder} instead.
    */
+  @Deprecated
   public CloudSolrClient(String zkHost) {
       this.zkHost = zkHost;
       this.clientIsInternal = true;
       this.myClient = HttpClientUtil.createClient(null);
-      this.lbClient = new LBHttpSolrClient(myClient);
+      this.lbClient = new LBHttpSolrClient.Builder()
+          .withHttpClient(myClient)
+          .build();
       this.lbClient.setRequestWriter(new BinaryRequestWriter());
       this.lbClient.setParser(new BinaryResponseParser());
       this.updatesToLeaders = true;
@@ -226,14 +230,15 @@ public class CloudSolrClient extends SolrClient {
    * @param httpClient
    *          the {@link HttpClient} instance to be used for all requests. The
    *          provided httpClient should use a multi-threaded connection manager.
+   *          
+   * @deprecated use {@link Builder} instead.
    */
+  @Deprecated
   public CloudSolrClient(String zkHost, HttpClient httpClient)  {
     this.zkHost = zkHost;
     this.clientIsInternal = httpClient == null;
     this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
-    this.lbClient = new LBHttpSolrClient(myClient);
-    this.lbClient.setRequestWriter(new BinaryRequestWriter());
-    this.lbClient.setParser(new BinaryResponseParser());
+    this.lbClient = createLBHttpSolrClient(myClient);
     this.updatesToLeaders = true;
     shutdownLBHttpSolrServer = true;
     lbClient.addQueryParams(STATE_VERSION);
@@ -256,7 +261,9 @@ public class CloudSolrClient extends SolrClient {
    * @throws IllegalArgumentException
    *           if the chroot value does not start with a forward slash.
    * @see #CloudSolrClient(String)
+   * @deprecated use {@link Builder} instead.
    */
+  @Deprecated
   public CloudSolrClient(Collection<String> zkHosts, String chroot) {
     this(zkHosts, chroot, null);
   }
@@ -281,47 +288,64 @@ public class CloudSolrClient extends SolrClient {
    * @throws IllegalArgumentException
    *           if the chroot value does not start with a forward slash.
    * @see #CloudSolrClient(String)
+   * @deprecated use {@link Builder} instead.
    */
+  @Deprecated
   public CloudSolrClient(Collection<String> zkHosts, String chroot, HttpClient httpClient) {
-    StringBuilder zkBuilder = new StringBuilder();
-    int lastIndexValue = zkHosts.size() - 1;
-    int i = 0;
-    for (String zkHost : zkHosts) {
-      zkBuilder.append(zkHost);
-      if (i < lastIndexValue) {
-        zkBuilder.append(",");
-      }
-      i++;
-    }
-    if (chroot != null) {
-      if (chroot.startsWith("/")) {
-        zkBuilder.append(chroot);
-      } else {
-        throw new IllegalArgumentException(
-            "The chroot must start with a forward slash.");
-      }
-    }
-
-    /* Log the constructed connection string and then initialize. */
-    log.info("Final constructed zkHost string: " + zkBuilder.toString());
-
-    this.zkHost = zkBuilder.toString();
+    this.zkHost = buildZkHostString(zkHosts, chroot);
     this.clientIsInternal = httpClient == null;
     this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
-    this.lbClient = new LBHttpSolrClient(myClient);
-    this.lbClient.setRequestWriter(new BinaryRequestWriter());
-    this.lbClient.setParser(new BinaryResponseParser());
+    this.lbClient = createLBHttpSolrClient(myClient);
     this.updatesToLeaders = true;
     shutdownLBHttpSolrServer = true;
   }
   
   /**
+   * Create a new client object that connects to Zookeeper and is always aware
+   * of the SolrCloud state. If there is a fully redundant Zookeeper quorum and
+   * SolrCloud has enough replicas for every shard in a collection, there is no
+   * single point of failure. Updates will be sent to shard leaders by default.
+   * 
+   * @param zkHosts
+   *          A Java Collection (List, Set, etc) of HOST:PORT strings, one for
+   *          each host in the zookeeper ensemble. Note that with certain
+   *          Collection types like HashSet, the order of hosts in the final
+   *          connect string may not be in the same order you added them.
+   * @param chroot
+   *          A chroot value for zookeeper, starting with a forward slash. If no
+   *          chroot is required, use null.
+   * @param httpClient
+   *          the {@link HttpClient} instance to be used for all requests. The provided httpClient should use a
+   *          multi-threaded connection manager.  If null, a default HttpClient will be used.
+   * @param lbSolrClient
+   *          LBHttpSolrServer instance for requests.  If null, a default HttpClient will be used.
+   * @param updatesToLeaders
+   *          If true, sends updates to shard leaders.
+   *
+   * @deprecated use {@link Builder} instead.  This will soon be a protected method, and will only
+   * be available for use in implementing subclasses.
+   */
+  @Deprecated
+  public CloudSolrClient(Collection<String> zkHosts, String chroot, HttpClient httpClient, LBHttpSolrClient lbSolrClient, boolean updatesToLeaders) {
+    this.zkHost = buildZkHostString(zkHosts, chroot);
+    this.updatesToLeaders = updatesToLeaders;
+    
+    this.clientIsInternal = httpClient == null;
+    this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
+    
+    this.shutdownLBHttpSolrServer = lbSolrClient == null;
+    this.lbClient = lbSolrClient == null ? createLBHttpSolrClient(myClient) : lbSolrClient;
+  }
+  
+  /**
    * @param zkHost
    *          A zookeeper client endpoint.
    * @param updatesToLeaders
    *          If true, sends updates only to shard leaders.
    * @see #CloudSolrClient(String) for full description and details on zkHost
+   * @deprecated use {@link CloudSolrClient.Builder} instead.
    */
+  @Deprecated
   public CloudSolrClient(String zkHost, boolean updatesToLeaders) {
     this(zkHost, updatesToLeaders, null);
   }
@@ -335,12 +359,16 @@ public class CloudSolrClient extends SolrClient {
    *          the {@link HttpClient} instance to be used for all requests. The provided httpClient should use a
    *          multi-threaded connection manager.
    * @see #CloudSolrClient(String) for full description and details on zkHost
+   * @deprecated use {@link CloudSolrClient.Builder} instead.
    */
+  @Deprecated
   public CloudSolrClient(String zkHost, boolean updatesToLeaders, HttpClient httpClient) {
     this.zkHost = zkHost;
     this.clientIsInternal = httpClient == null;
     this.myClient = httpClient == null ? HttpClientUtil.createClient(null) : httpClient;
-    this.lbClient = new LBHttpSolrClient(myClient);
+    this.lbClient = new LBHttpSolrClient.Builder()
+        .withHttpClient(myClient)
+        .build();
     this.lbClient.setRequestWriter(new BinaryRequestWriter());
     this.lbClient.setParser(new BinaryResponseParser());
     this.updatesToLeaders = updatesToLeaders;
@@ -362,7 +390,9 @@ public class CloudSolrClient extends SolrClient {
    * @param lbClient
    *          LBHttpSolrServer instance for requests.
    * @see #CloudSolrClient(String) for full description and details on zkHost
+   * @deprecated use {@link CloudSolrClient.Builder} instead.
    */
+  @Deprecated
   public CloudSolrClient(String zkHost, LBHttpSolrClient lbClient) {
     this(zkHost, lbClient, true);
   }
@@ -375,7 +405,9 @@ public class CloudSolrClient extends SolrClient {
    * @param updatesToLeaders
    *          If true, sends updates only to shard leaders.
    * @see #CloudSolrClient(String) for full description and details on zkHost
+   * @deprecated use {@link Builder} instead.
    */
+  @Deprecated
   public CloudSolrClient(String zkHost, LBHttpSolrClient lbClient, boolean updatesToLeaders) {
     this.zkHost = zkHost;
     this.lbClient = lbClient;
@@ -1348,4 +1380,137 @@ public class CloudSolrClient extends SolrClient {
   public void setSoTimeout(int timeout) {
     this.lbClient.setSoTimeout(timeout);
   }
+
+  private static LBHttpSolrClient createLBHttpSolrClient(HttpClient httpClient) {
+    final LBHttpSolrClient lbClient = new LBHttpSolrClient.Builder()
+        .withHttpClient(httpClient)
+        .build();
+    lbClient.setRequestWriter(new BinaryRequestWriter());
+    lbClient.setParser(new BinaryResponseParser());
+    
+    return lbClient;
+  }
+  
+  private static String buildZkHostString(Collection<String> zkHosts, String chroot) {
+    if (zkHosts == null || zkHosts.isEmpty()) {
+      throw new IllegalArgumentException("Cannot create CloudSearchClient without valid ZooKeeper host; none specified!");
+    }
+    
+    StringBuilder zkBuilder = new StringBuilder();
+    int lastIndexValue = zkHosts.size() - 1;
+    int i = 0;
+    for (String zkHost : zkHosts) {
+      zkBuilder.append(zkHost);
+      if (i < lastIndexValue) {
+        zkBuilder.append(",");
+      }
+      i++;
+    }
+    if (chroot != null) {
+      if (chroot.startsWith("/")) {
+        zkBuilder.append(chroot);
+      } else {
+        throw new IllegalArgumentException(
+            "The chroot must start with a forward slash.");
+      }
+    }
+
+    /* Log the constructed connection string and then initialize. */
+    final String zkHostString = zkBuilder.toString();
+    log.info("Final constructed zkHost string: " + zkHostString);
+    return zkHostString;
+  }
+  
+  /**
+   * Constructs {@link CloudSolrClient} instances from provided configuration.
+   */
+  public static class Builder {
+    private Collection<String> zkHosts;
+    private HttpClient httpClient;
+    private String zkChroot;
+    private LBHttpSolrClient loadBalancedSolrClient;
+    private boolean shardLeadersOnly;
+    
+    public Builder() {
+      this.zkHosts = new ArrayList();
+      this.shardLeadersOnly = true;
+    }
+    
+    /**
+     * Provide a ZooKeeper client endpoint to be used when configuring {@link CloudSolrClient} instances.
+     * 
+     * Method may be called multiple times.  All provided values will be used.
+     * 
+     * @param zkHost
+     *          The client endpoint of the ZooKeeper quorum containing the cloud
+     *          state.
+     */
+    public Builder withZkHost(String zkHost) {
+      this.zkHosts.add(zkHost);
+      return this;
+    }
+    
+    /**
+     * Provides a {@link HttpClient} for the builder to use when creating clients.
+     */
+    public Builder withHttpClient(HttpClient httpClient) {
+      this.httpClient = httpClient;
+      return this;
+    }
+    
+    /**
+     * Provide a series of ZooKeeper client endpoints for the builder to use when creating clients.
+     * 
+     * Method may be called multiple times.  All provided values will be used.
+     * 
+     * @param zkHosts
+     *          A Java Collection (List, Set, etc) of HOST:PORT strings, one for
+     *          each host in the ZooKeeper ensemble. Note that with certain
+     *          Collection types like HashSet, the order of hosts in the final
+     *          connect string may not be in the same order you added them.
+     */
+    public Builder withZkHost(Collection<String> zkHosts) {
+      this.zkHosts.addAll(zkHosts);
+      return this;
+    }
+
+    /**
+     * Provides a ZooKeeper chroot for the builder to use when creating clients.
+     */
+    public Builder withZkChroot(String zkChroot) {
+      this.zkChroot = zkChroot;
+      return this;
+    }
+    
+    /**
+     * Provides a {@link LBHttpSolrClient} for the builder to use when creating clients.
+     */
+    public Builder withLBHttpSolrClient(LBHttpSolrClient loadBalancedSolrClient) {
+      this.loadBalancedSolrClient = loadBalancedSolrClient;
+      return this;
+    }
+
+    /**
+     * Tells {@link Builder} that created clients should send updats only to shard leaders.
+     */
+    public Builder sendUpdatesOnlyToShardLeaders() {
+      shardLeadersOnly = true;
+      return this;
+    }
+    
+    /**
+     * Tells {@link Builder} that created clients should send updates to all replicas for a shard.
+     */
+    public Builder sendUpdatesToAllReplicasInShard() {
+      shardLeadersOnly = false;
+      return this;
+    }
+
+    /**
+     * Create a {@link CloudSolrClient} based on the provided configuration.
+     */
+    public CloudSolrClient build() {
+      return new CloudSolrClient(zkHosts, zkChroot, httpClient, loadBalancedSolrClient, shardLeadersOnly);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/ConcurrentUpdateSolrClient.java
----------------------------------------------------------------------
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 d197e4b..2551957 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
@@ -16,11 +16,25 @@
  */
 package org.apache.solr.client.solrj.impl;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.invoke.MethodHandles;
+import java.nio.charset.StandardCharsets;
+import java.util.LinkedList;
+import java.util.Locale;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.NameValuePair;
 import org.apache.http.client.HttpClient;
-import org.apache.http.client.config.RequestConfig.Builder;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.ContentProducer;
 import org.apache.http.entity.EntityTemplate;
@@ -46,21 +60,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.MDC;
 
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.lang.invoke.MethodHandles;
-import java.nio.charset.StandardCharsets;
-import java.util.LinkedList;
-import java.util.Locale;
-import java.util.Queue;
-import java.util.Set;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.TimeUnit;
-
 /**
  * ConcurrentUpdateSolrClient buffers all added documents and writes
  * them into open HTTP connections. This class is thread safe.
@@ -99,7 +98,10 @@ public class ConcurrentUpdateSolrClient extends SolrClient {
    *          The buffer size before the documents are sent to the server
    * @param threadCount
    *          The number of background threads used to empty the queue
+   *          
+   * @deprecated use {@link Builder} instead.
    */
+  @Deprecated
   public ConcurrentUpdateSolrClient(String solrServerUrl, int queueSize,
                                     int threadCount) {
     this(solrServerUrl, null, queueSize, threadCount);
@@ -107,6 +109,10 @@ public class ConcurrentUpdateSolrClient extends SolrClient {
     internalHttpClient = true;
   }
   
+  /**
+   * @deprecated use {@link Builder} instead.
+   */
+  @Deprecated
   public ConcurrentUpdateSolrClient(String solrServerUrl,
                                     HttpClient client, int queueSize, int threadCount) {
     this(solrServerUrl, client, queueSize, threadCount, ExecutorUtil.newMDCAwareCachedThreadPool(
@@ -116,7 +122,10 @@ public class ConcurrentUpdateSolrClient extends SolrClient {
 
   /**
    * Uses the supplied HttpClient to send documents to the Solr server.
+   * 
+   * @deprecated use {@link Builder} instead.
    */
+  @Deprecated
   public ConcurrentUpdateSolrClient(String solrServerUrl,
                                     HttpClient client, int queueSize, int threadCount, ExecutorService es) {
     this(solrServerUrl, client, queueSize, threadCount, es, false);
@@ -124,16 +133,30 @@ public class ConcurrentUpdateSolrClient extends SolrClient {
   
   /**
    * Uses the supplied HttpClient to send documents to the Solr server.
+   * 
+   * @deprecated use {@link Builder} instead.  This will soon be a
+   * protected method, and will only be available for use in implementing subclasses.
    */
+  @Deprecated
   public ConcurrentUpdateSolrClient(String solrServerUrl,
                                     HttpClient client, int queueSize, int threadCount, ExecutorService es, boolean streamDeletes) {
-    this.client = new HttpSolrClient(solrServerUrl, client);
+    this.internalHttpClient = (client == null);
+    this.client = new HttpSolrClient.Builder(solrServerUrl)
+        .withHttpClient(client)
+        .build();
     this.client.setFollowRedirects(false);
     queue = new LinkedBlockingQueue<>(queueSize);
     this.threadCount = threadCount;
     runners = new LinkedList<>();
-    scheduler = es;
     this.streamDeletes = streamDeletes;
+    
+    if (es != null) {
+      scheduler = es;
+      shutdownExecutor = false;
+    } else {
+      scheduler = ExecutorUtil.newMDCAwareCachedThreadPool(new SolrjNamedThreadFactory("concurrentUpdateScheduler"));
+      shutdownExecutor = true;
+    }
   }
 
   public Set<String> getQueryParams() {
@@ -278,7 +301,7 @@ public class ConcurrentUpdateSolrClient extends SolrClient {
           method = new HttpPost(client.getBaseURL() + "/update"
               + requestParams.toQueryString());
           
-          Builder requestConfigBuilder = HttpClientUtil.createDefaultRequestConfigBuilder();
+          org.apache.http.client.config.RequestConfig.Builder requestConfigBuilder = HttpClientUtil.createDefaultRequestConfigBuilder();
           if (soTimeout != null) {
             requestConfigBuilder.setSocketTimeout(soTimeout);
           }
@@ -544,4 +567,91 @@ public class ConcurrentUpdateSolrClient extends SolrClient {
   public void setRequestWriter(RequestWriter requestWriter) {
     client.setRequestWriter(requestWriter);
   }
+  
+  /**
+   * Constructs {@link ConcurrentUpdateSolrClient} instances from provided configuration.
+   */
+  public static class Builder {
+    private String baseSolrUrl;
+    private HttpClient httpClient;
+    private int queueSize;
+    private int threadCount;
+    private ExecutorService executorService;
+    private boolean streamDeletes;
+
+    /**
+     * Create a Builder object, based on the provided Solr URL.
+     * 
+     * @param baseSolrUrl the base URL of the Solr server that will be targeted by any created clients.
+     */
+    public Builder(String baseSolrUrl) {
+      this.baseSolrUrl = baseSolrUrl;
+    }
+
+    /**
+     * Provides a {@link HttpClient} for the builder to use when creating clients.
+     */
+    public Builder withHttpClient(HttpClient httpClient) {
+      this.httpClient = httpClient;
+      return this;
+    }
+    
+    /**
+     * The number of documents to batch together before sending to Solr.
+     */
+    public Builder withQueueSize(int queueSize) {
+      if (queueSize <= 0) {
+        throw new IllegalArgumentException("queueSize must be a positive integer.");
+      }
+      this.queueSize = queueSize;
+      return this;
+    }
+    
+    /**
+     * The number of threads used to empty {@link ConcurrentUpdateSolrClient}s queue.
+     */
+    public Builder withThreadCount(int threadCount) {
+      if (threadCount <= 0) {
+        throw new IllegalArgumentException("threadCount must be a positive integer.");
+      }
+      
+      this.threadCount = threadCount;
+      return this;
+    }
+    
+    /**
+     * Provides the {@link ExecutorService} for clients to use when servicing requests.
+     */
+    public Builder withExecutorService(ExecutorService executorService) {
+      this.executorService = executorService;
+      return this;
+    }
+    
+    /**
+     * Configures created clients to always stream delete requests.
+     */
+    public Builder alwaysStreamDeletes() {
+      this.streamDeletes = true;
+      return this;
+    }
+    
+    /**
+     * Configures created clients to not stream delete requests.
+     */
+    public Builder neverStreamDeletes() {
+      this.streamDeletes = false;
+      return this;
+    }
+    
+    /**
+     * Create a {@link ConcurrentUpdateSolrClient} based on the provided configuration options.
+     */
+    public ConcurrentUpdateSolrClient build() {
+      if (baseSolrUrl == null) {
+        throw new IllegalArgumentException("Cannot create HttpSolrClient without a valid baseSolrUrl!");
+      }
+      
+      return new ConcurrentUpdateSolrClient(baseSolrUrl, httpClient, queueSize, threadCount, executorService, streamDeletes);
+    }
+  }
 }


[3/3] lucene-solr:master: SOLR-8097: Implement builder pattern design for constructing SolrJ clients and deprecate direct construction of clients

Posted by an...@apache.org.
SOLR-8097: Implement builder pattern design for constructing SolrJ clients and deprecate direct construction of clients


Project: http://git-wip-us.apache.org/repos/asf/lucene-solr/repo
Commit: http://git-wip-us.apache.org/repos/asf/lucene-solr/commit/b02b026b
Tree: http://git-wip-us.apache.org/repos/asf/lucene-solr/tree/b02b026b
Diff: http://git-wip-us.apache.org/repos/asf/lucene-solr/diff/b02b026b

Branch: refs/heads/master
Commit: b02b026b7d979a9dac3c549c156dd9706e6fc5ba
Parents: 1848477
Author: Anshum Gupta <an...@apache.org>
Authored: Thu Apr 7 15:43:24 2016 -0700
Committer: Anshum Gupta <an...@apache.org>
Committed: Thu Apr 7 15:57:49 2016 -0700

----------------------------------------------------------------------
 solr/CHANGES.txt                                |   3 +
 .../handler/dataimport/SolrEntityProcessor.java |  10 +-
 .../dataimport/TestContentStreamDataSource.java |   4 +-
 .../TestSolrEntityProcessorEndToEnd.java        |   2 +-
 .../src/java/org/apache/solr/hadoop/GoLive.java |   6 +-
 .../solr/hadoop/MorphlineGoLiveMiniMRTest.java  |   4 +-
 .../solr/SafeConcurrentUpdateSolrClient.java    |   2 +-
 .../solr/morphlines/solr/SolrLocator.java       |   5 +-
 .../solr/AbstractSolrMorphlineTestBase.java     |   2 +-
 .../cloud/LeaderInitiatedRecoveryThread.java    |   2 +-
 .../OverseerAutoReplicaFailoverThread.java      |  32 ++-
 .../cloud/OverseerCollectionMessageHandler.java |   2 +-
 .../org/apache/solr/cloud/RecoveryStrategy.java |   5 +-
 .../org/apache/solr/cloud/SyncStrategy.java     |   2 +-
 .../org/apache/solr/cloud/ZkController.java     |   3 +-
 .../apache/solr/cloud/rule/SnitchContext.java   |   3 +-
 .../solr/handler/CdcrReplicatorManager.java     |  18 +-
 .../apache/solr/handler/CdcrRequestHandler.java |   2 +-
 .../solr/handler/CdcrUpdateLogSynchronizer.java |   2 +-
 .../org/apache/solr/handler/IndexFetcher.java   |  12 +-
 .../apache/solr/handler/SolrConfigHandler.java  |   3 +-
 .../solr/handler/admin/CollectionsHandler.java  |   3 +-
 .../handler/component/HttpShardHandler.java     |   5 +-
 .../component/HttpShardHandlerFactory.java      |   5 +-
 .../component/IterativeMergeStrategy.java       |   7 +-
 .../apache/solr/schema/ManagedIndexSchema.java  |   2 +-
 .../apache/solr/update/SolrCmdDistributor.java  |   3 +-
 .../solr/update/StreamingSolrClients.java       |  66 +++---
 .../src/java/org/apache/solr/util/SolrCLI.java  |  21 +-
 .../org/apache/solr/TestTolerantSearch.java     |   6 +-
 .../solr/client/solrj/ConnectionReuseTest.java  |   6 +-
 .../solrj/embedded/TestJettySolrRunner.java     |   3 +-
 .../apache/solr/cloud/AliasIntegrationTest.java |  14 +-
 .../solr/cloud/AsyncMigrateRouteKeyTest.java    |   2 +-
 .../solr/cloud/BaseCdcrDistributedZkTest.java   |   4 +-
 .../solr/cloud/BasicDistributedZk2Test.java     |   6 +-
 .../solr/cloud/BasicDistributedZkTest.java      |  14 +-
 .../cloud/ChaosMonkeyNothingIsSafeTest.java     |  46 ++--
 .../apache/solr/cloud/CollectionReloadTest.java |   2 +-
 .../cloud/CollectionsAPIDistributedZkTest.java  |  12 +-
 .../solr/cloud/CollectionsAPISolrJTest.java     |   2 +-
 ...ConcurrentDeleteAndCreateCollectionTest.java |   6 +-
 .../apache/solr/cloud/CustomCollectionTest.java |  12 +-
 .../solr/cloud/DeleteInactiveReplicaTest.java   |   2 +-
 .../apache/solr/cloud/DeleteReplicaTest.java    |   4 +-
 .../org/apache/solr/cloud/DeleteShardTest.java  |   6 +-
 .../solr/cloud/DistributedVersionInfoTest.java  |   8 +-
 .../org/apache/solr/cloud/ForceLeaderTest.java  |   2 +-
 .../cloud/FullSolrCloudDistribCmdsTest.java     |   2 +-
 .../apache/solr/cloud/HttpPartitionTest.java    |   2 +-
 .../LeaderInitiatedRecoveryOnCommitTest.java    |   2 +-
 ...aderInitiatedRecoveryOnShardRestartTest.java |   2 +-
 .../apache/solr/cloud/MigrateRouteKeyTest.java  |   4 +-
 .../solr/cloud/ReplicationFactorTest.java       |   2 +-
 .../org/apache/solr/cloud/SSLMigrationTest.java |   2 +-
 .../org/apache/solr/cloud/ShardSplitTest.java   |  33 ++-
 .../org/apache/solr/cloud/SyncSliceTest.java    |   2 +-
 .../solr/cloud/TestCloudDeleteByQuery.java      |  10 +-
 .../apache/solr/cloud/TestConfigSetsAPI.java    |  20 +-
 .../cloud/TestConfigSetsAPIExclusivity.java     |   4 +-
 .../solr/cloud/TestConfigSetsAPIZkFailure.java  |   4 +-
 .../org/apache/solr/cloud/TestCryptoKeys.java   |   2 +-
 .../solr/cloud/TestMiniSolrCloudClusterSSL.java |   2 +-
 .../cloud/TestRandomRequestDistribution.java    |   4 +-
 .../cloud/TestRequestStatusCollectionAPI.java   |   2 +-
 .../cloud/TestTolerantUpdateProcessorCloud.java |  10 +-
 .../TestTolerantUpdateProcessorRandomCloud.java |   2 +-
 .../solr/cloud/UnloadDistributedZkTest.java     |  30 +--
 .../HdfsWriteToMultipleCollectionsTest.java     |   2 +-
 .../apache/solr/cloud/hdfs/StressHdfsTest.java  |   2 +-
 .../solr/core/OpenCloseCoreStressTest.java      |   4 +-
 .../apache/solr/core/TestDynamicLoading.java    |   2 +-
 .../solr/handler/TestReplicationHandler.java    |   5 +-
 .../handler/TestReplicationHandlerBackup.java   |   3 +-
 .../apache/solr/handler/TestRestoreCore.java    |   3 +-
 .../handler/admin/CoreAdminHandlerTest.java     |   4 +-
 .../DistributedDebugComponentTest.java          |   6 +-
 .../DistributedQueryElevationComponentTest.java |   3 +-
 .../test/org/apache/solr/search/TestSolrJ.java  |   4 +-
 .../solr/search/stats/TestDistribIDF.java       |   8 +-
 .../solr/security/BasicAuthIntegrationTest.java |   3 +-
 .../processor/TestNamedUpdateProcessors.java    |   3 +-
 .../apache/solr/util/TestSolrCLIRunExample.java |   4 +-
 .../solr/client/solrj/impl/CloudSolrClient.java | 229 ++++++++++++++++---
 .../solrj/impl/ConcurrentUpdateSolrClient.java  | 148 ++++++++++--
 .../solr/client/solrj/impl/HttpSolrClient.java  |  77 ++++++-
 .../client/solrj/impl/LBHttpSolrClient.java     | 126 ++++++++--
 .../solr/client/solrj/io/SolrClientCache.java   |   9 +-
 .../solrj/io/sql/DatabaseMetaDataImpl.java      |   4 +-
 .../client/solrj/io/stream/CloudSolrStream.java |   7 +-
 .../client/solrj/io/stream/FacetStream.java     |   8 +-
 .../solr/client/solrj/io/stream/SolrStream.java |   4 +-
 .../client/solrj/io/stream/StatsStream.java     |   7 +-
 .../client/solrj/io/stream/TopicStream.java     |   8 +-
 .../client/solrj/io/stream/UpdateStream.java    |   5 +-
 .../client/solrj/SolrExampleBinaryTest.java     |   2 +-
 .../solr/client/solrj/SolrExampleTests.java     |   2 +-
 .../solr/client/solrj/SolrExampleXMLTest.java   |   2 +-
 .../solr/client/solrj/SolrExceptionTest.java    |   4 +-
 .../client/solrj/SolrSchemalessExampleTest.java |   2 +-
 .../solr/client/solrj/TestLBHttpSolrClient.java |   8 +-
 .../solrj/embedded/SolrExampleJettyTest.java    |   2 +-
 .../embedded/SolrExampleStreamingTest.java      |  23 +-
 .../solrj/impl/BasicHttpSolrClientTest.java     |  47 ++--
 .../solrj/impl/CloudSolrClientBuilderTest.java  |  90 ++++++++
 .../client/solrj/impl/CloudSolrClientTest.java  |  21 +-
 .../ConcurrentUpdateSolrClientBuilderTest.java  |  33 +++
 .../impl/ConcurrentUpdateSolrClientTest.java    |  37 ++-
 .../solrj/impl/HttpSolrClientBuilderTest.java   |  76 ++++++
 .../solrj/impl/LBHttpSolrClientBuilderTest.java |  65 ++++++
 .../solr/BaseDistributedSearchTestCase.java     |   2 +-
 .../java/org/apache/solr/SolrJettyTestBase.java |   2 +-
 .../java/org/apache/solr/SolrTestCaseHS.java    |  40 ++--
 .../java/org/apache/solr/SolrTestCaseJ4.java    | 142 ++++++++++++
 .../cloud/AbstractFullDistribZkTestBase.java    |  18 +-
 .../apache/solr/cloud/MiniSolrCloudCluster.java |   5 +-
 116 files changed, 1386 insertions(+), 459 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 33e9a3e..1175123 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -140,6 +140,9 @@ Other Changes
 * SOLR-8892: Allow SolrInfoMBeans to return different statistics for /jmx vs web ui calls.
   (Gregory Chanan, Mark Miller)
 
+* SOLR-8097: Implement builder pattern design for constructing SolrJ clients and also deprecate direct construction
+  of client objects. (Jason Gerlowski, Shawn Heisey, Anshum Gupta)
+
 ==================  6.0.0 ==================
 
 Consult the LUCENE_CHANGES.txt file for additional, low level, changes in this release

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java
----------------------------------------------------------------------
diff --git a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java
index cece0cc..5e62731 100644
--- a/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java
+++ b/solr/contrib/dataimporthandler/src/java/org/apache/solr/handler/dataimport/SolrEntityProcessor.java
@@ -22,6 +22,7 @@ import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
 import org.apache.solr.client.solrj.impl.XMLResponseParser;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.common.SolrDocument;
@@ -111,11 +112,16 @@ public class SolrEntityProcessor extends EntityProcessorBase {
       // (wt="javabin|xml") default is javabin
       if ("xml".equals(context.getResolvedEntityAttribute(CommonParams.WT))) {
         // TODO: it doesn't matter for this impl when passing a client currently, but we should close this!
-        solrClient = new HttpSolrClient(url.toExternalForm(), client, new XMLResponseParser());
+        solrClient = new Builder(url.toExternalForm())
+            .withHttpClient(client)
+            .withResponseParser(new XMLResponseParser())
+            .build();
         LOG.info("using XMLResponseParser");
       } else {
         // TODO: it doesn't matter for this impl when passing a client currently, but we should close this!
-        solrClient = new HttpSolrClient(url.toExternalForm(), client);
+        solrClient = new Builder(url.toExternalForm())
+            .withHttpClient(client)
+            .build();
         LOG.info("using BinaryResponseParser");
       }
     } catch (MalformedURLException e) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java
----------------------------------------------------------------------
diff --git a/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java
index 453f571..95af5f9 100644
--- a/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java
+++ b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestContentStreamDataSource.java
@@ -69,7 +69,7 @@ public class TestContentStreamDataSource extends AbstractDataImportHandlerTestCa
     params.set("command", "full-import");
     params.set("clean", "false");
     req.setParams(params);
-    try (HttpSolrClient solrClient = new HttpSolrClient(buildUrl(jetty.getLocalPort(), "/solr/collection1"))) {
+    try (HttpSolrClient solrClient = getHttpSolrClient(buildUrl(jetty.getLocalPort(), "/solr/collection1"))) {
       solrClient.request(req);
       ModifiableSolrParams qparams = new ModifiableSolrParams();
       qparams.add("q", "*:*");
@@ -89,7 +89,7 @@ public class TestContentStreamDataSource extends AbstractDataImportHandlerTestCa
         "clean", "false", UpdateParams.COMMIT, "false", 
         UpdateParams.COMMIT_WITHIN, "1000");
     req.setParams(params);
-    try (HttpSolrClient solrServer = new HttpSolrClient(buildUrl(jetty.getLocalPort(), "/solr/collection1"))) {
+    try (HttpSolrClient solrServer = getHttpSolrClient(buildUrl(jetty.getLocalPort(), "/solr/collection1"))) {
       solrServer.request(req);
       Thread.sleep(100);
       ModifiableSolrParams queryAll = params("q", "*");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java
----------------------------------------------------------------------
diff --git a/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java
index abefc49..8ef94c0 100644
--- a/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java
+++ b/solr/contrib/dataimporthandler/src/test/org/apache/solr/handler/dataimport/TestSolrEntityProcessorEndToEnd.java
@@ -282,7 +282,7 @@ public class TestSolrEntityProcessorEndToEnd extends AbstractDataImportHandlerTe
       sidl.add(sd);
     }
 
-    try (HttpSolrClient solrServer = new HttpSolrClient(getSourceUrl())) {
+    try (HttpSolrClient solrServer = getHttpSolrClient(getSourceUrl())) {
       solrServer.setConnectionTimeout(15000);
       solrServer.setSoTimeout(30000);
       solrServer.add(sidl);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/GoLive.java
----------------------------------------------------------------------
diff --git a/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/GoLive.java b/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/GoLive.java
index bd48c64..5b1c343 100644
--- a/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/GoLive.java
+++ b/solr/contrib/map-reduce/src/java/org/apache/solr/hadoop/GoLive.java
@@ -90,7 +90,7 @@ class GoLive {
           Callable<Request> task = () -> {
             Request req = new Request();
             LOG.info("Live merge " + dir.getPath() + " into " + mergeUrl);
-            try (final HttpSolrClient client = new HttpSolrClient(mergeUrl)) {
+            try (final HttpSolrClient client = new HttpSolrClient.Builder(mergeUrl).build()) {
               CoreAdminRequest.MergeIndexes mergeRequest = new CoreAdminRequest.MergeIndexes();
               mergeRequest.setCoreName(name);
               mergeRequest.setIndexDirs(Arrays.asList(dir.getPath().toString() + "/data/index"));
@@ -138,7 +138,7 @@ class GoLive {
       try {
         LOG.info("Committing live merge...");
         if (options.zkHost != null) {
-          try (CloudSolrClient server = new CloudSolrClient(options.zkHost)) {
+          try (CloudSolrClient server = new CloudSolrClient.Builder().withZkHost(options.zkHost).build()) {
             server.setDefaultCollection(options.collection);
             server.commit();
           }
@@ -146,7 +146,7 @@ class GoLive {
           for (List<String> urls : options.shardUrls) {
             for (String url : urls) {
               // TODO: we should do these concurrently
-              try (HttpSolrClient server = new HttpSolrClient(url)) {
+              try (HttpSolrClient server = new HttpSolrClient.Builder(url).build()) {
                 server.commit();
               }
             }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/contrib/map-reduce/src/test/org/apache/solr/hadoop/MorphlineGoLiveMiniMRTest.java
----------------------------------------------------------------------
diff --git a/solr/contrib/map-reduce/src/test/org/apache/solr/hadoop/MorphlineGoLiveMiniMRTest.java b/solr/contrib/map-reduce/src/test/org/apache/solr/hadoop/MorphlineGoLiveMiniMRTest.java
index 95ed9b2..ce3d8c4 100644
--- a/solr/contrib/map-reduce/src/test/org/apache/solr/hadoop/MorphlineGoLiveMiniMRTest.java
+++ b/solr/contrib/map-reduce/src/test/org/apache/solr/hadoop/MorphlineGoLiveMiniMRTest.java
@@ -380,7 +380,7 @@ public class MorphlineGoLiveMiniMRTest extends AbstractFullDistribZkTestBase {
     String[] args = new String[]{};
     List<String> argList = new ArrayList<>();
 
-    try (HttpSolrClient server = new HttpSolrClient(cloudJettys.get(0).url)) {
+    try (HttpSolrClient server = getHttpSolrClient(cloudJettys.get(0).url)) {
 
       args = new String[]{
           "--solr-home-dir=" + MINIMR_CONF_DIR.getAbsolutePath(),
@@ -706,7 +706,7 @@ public class MorphlineGoLiveMiniMRTest extends AbstractFullDistribZkTestBase {
       Collection<Replica> replicas = slice.getReplicas();
       long found = -1;
       for (Replica replica : replicas) {
-        try (HttpSolrClient client = new HttpSolrClient(new ZkCoreNodeProps(replica).getCoreUrl())) {
+        try (HttpSolrClient client = getHttpSolrClient(new ZkCoreNodeProps(replica).getCoreUrl())) {
           SolrQuery query = new SolrQuery("*:*");
           query.set("distrib", false);
           QueryResponse replicaResults = client.query(query);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SafeConcurrentUpdateSolrClient.java
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SafeConcurrentUpdateSolrClient.java b/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SafeConcurrentUpdateSolrClient.java
index 1d632f1..a5fb929 100644
--- a/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SafeConcurrentUpdateSolrClient.java
+++ b/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SafeConcurrentUpdateSolrClient.java
@@ -39,7 +39,7 @@ final class SafeConcurrentUpdateSolrClient extends ConcurrentUpdateSolrClient {
   }
 
   public SafeConcurrentUpdateSolrClient(String solrServerUrl, HttpClient client, int queueSize, int threadCount) {
-    super(solrServerUrl, client, queueSize, threadCount);
+    super(solrServerUrl, client, queueSize, threadCount, null, false);
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SolrLocator.java
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SolrLocator.java b/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SolrLocator.java
index 4acb9ac..39cee54 100644
--- a/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SolrLocator.java
+++ b/solr/contrib/morphlines-core/src/java/org/apache/solr/morphlines/solr/SolrLocator.java
@@ -30,6 +30,7 @@ import com.typesafe.config.ConfigRenderOptions;
 import com.typesafe.config.ConfigUtil;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
 import org.apache.solr.common.cloud.SolrZkClient;
 import org.apache.solr.core.SolrConfig;
 import org.apache.solr.core.SolrResourceLoader;
@@ -92,7 +93,9 @@ public class SolrLocator {
       if (collectionName == null || collectionName.length() == 0) {
         throw new MorphlineCompilationException("Parameter 'zkHost' requires that you also pass parameter 'collection'", config);
       }
-      CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost);
+      CloudSolrClient cloudSolrClient = new Builder()
+          .withZkHost(zkHost)
+          .build();
       cloudSolrClient.setDefaultCollection(collectionName);
       cloudSolrClient.connect();
       return new SolrClientDocumentLoader(cloudSolrClient, batchSize);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/contrib/morphlines-core/src/test/org/apache/solr/morphlines/solr/AbstractSolrMorphlineTestBase.java
----------------------------------------------------------------------
diff --git a/solr/contrib/morphlines-core/src/test/org/apache/solr/morphlines/solr/AbstractSolrMorphlineTestBase.java b/solr/contrib/morphlines-core/src/test/org/apache/solr/morphlines/solr/AbstractSolrMorphlineTestBase.java
index 9c79c07..6fd7cdb 100644
--- a/solr/contrib/morphlines-core/src/test/org/apache/solr/morphlines/solr/AbstractSolrMorphlineTestBase.java
+++ b/solr/contrib/morphlines-core/src/test/org/apache/solr/morphlines/solr/AbstractSolrMorphlineTestBase.java
@@ -123,7 +123,7 @@ public class AbstractSolrMorphlineTestBase extends SolrTestCaseJ4 {
     if (EXTERNAL_SOLR_SERVER_URL != null) {
       //solrServer = new ConcurrentUpdateSolrServer(EXTERNAL_SOLR_SERVER_URL, 2, 2);
       //solrServer = new SafeConcurrentUpdateSolrServer(EXTERNAL_SOLR_SERVER_URL, 2, 2);
-      solrClient = new HttpSolrClient(EXTERNAL_SOLR_SERVER_URL);
+      solrClient = getHttpSolrClient(EXTERNAL_SOLR_SERVER_URL);
       ((HttpSolrClient) solrClient).setParser(new XMLResponseParser());
     } else {
       if (TEST_WITH_EMBEDDED_SOLR_SERVER) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java b/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java
index 589ed83..4389d9e 100644
--- a/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java
+++ b/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java
@@ -201,7 +201,7 @@ public class LeaderInitiatedRecoveryThread extends Thread {
         log.info("Asking core={} coreNodeName={} on " + recoveryUrl + " to recover", coreNeedingRecovery, replicaCoreNodeName);
       }
 
-      try (HttpSolrClient client = new HttpSolrClient(recoveryUrl)) {
+      try (HttpSolrClient client = new HttpSolrClient.Builder(recoveryUrl).build()) {
         client.setSoTimeout(60000);
         client.setConnectionTimeout(15000);
         try {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java b/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java
index a9f8bdd..f94ffcc 100644
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java
@@ -16,9 +16,22 @@
  */
 package org.apache.solr.cloud;
 
+import java.io.Closeable;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
+
 import com.google.common.cache.Cache;
 import com.google.common.cache.CacheBuilder;
-
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.Create;
 import org.apache.solr.common.SolrException;
@@ -34,21 +47,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.slf4j.MDC;
 
-import java.io.Closeable;
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-
 
 // TODO: how to tmp exclude nodes?
 
@@ -434,7 +432,7 @@ public class OverseerAutoReplicaFailoverThread implements Runnable, Closeable {
       final String createUrl, final String dataDir, final String ulogDir,
       final String coreNodeName, final String coreName) {
 
-    try (HttpSolrClient client = new HttpSolrClient(createUrl)) {
+    try (HttpSolrClient client = new HttpSolrClient.Builder(createUrl).build()) {
       log.debug("create url={}", createUrl);
       client.setConnectionTimeout(30000);
       client.setSoTimeout(60000);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java b/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
index 78db473..503ff29 100644
--- a/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
+++ b/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionMessageHandler.java
@@ -1315,7 +1315,7 @@ public class OverseerCollectionMessageHandler implements OverseerMessageHandler
 
   static UpdateResponse softCommit(String url) throws SolrServerException, IOException {
 
-    try (HttpSolrClient client = new HttpSolrClient(url)) {
+    try (HttpSolrClient client = new HttpSolrClient.Builder(url).build()) {
       client.setConnectionTimeout(30000);
       client.setSoTimeout(120000);
       UpdateRequest ureq = new UpdateRequest();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java b/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
index 5daa6af..61b3f90 100644
--- a/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
+++ b/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
@@ -17,7 +17,6 @@
 package org.apache.solr.cloud;
 
 import java.io.Closeable;
-
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
@@ -195,7 +194,7 @@ public class RecoveryStrategy extends Thread implements Closeable {
 
   private void commitOnLeader(String leaderUrl) throws SolrServerException,
       IOException {
-    try (HttpSolrClient client = new HttpSolrClient(leaderUrl)) {
+    try (HttpSolrClient client = new HttpSolrClient.Builder(leaderUrl).build()) {
       client.setConnectionTimeout(30000);
       UpdateRequest ureq = new UpdateRequest();
       ureq.setParams(new ModifiableSolrParams());
@@ -575,7 +574,7 @@ public class RecoveryStrategy extends Thread implements Closeable {
   private void sendPrepRecoveryCmd(String leaderBaseUrl, String leaderCoreName, Slice slice)
       throws SolrServerException, IOException, InterruptedException, ExecutionException {
 
-    try (HttpSolrClient client = new HttpSolrClient(leaderBaseUrl)) {
+    try (HttpSolrClient client = new HttpSolrClient.Builder(leaderBaseUrl).build()) {
       client.setConnectionTimeout(30000);
       WaitForState prepCmd = new WaitForState();
       prepCmd.setCoreName(leaderCoreName);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java b/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
index cedcff9..b1d69be 100644
--- a/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
+++ b/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
@@ -292,7 +292,7 @@ public class SyncStrategy {
         recoverRequestCmd.setAction(CoreAdminAction.REQUESTRECOVERY);
         recoverRequestCmd.setCoreName(coreName);
         
-        try (HttpSolrClient client = new HttpSolrClient(baseUrl, SyncStrategy.this.client)) {
+        try (HttpSolrClient client = new HttpSolrClient.Builder(baseUrl).withHttpClient(SyncStrategy.this.client).build()) {
           client.setConnectionTimeout(30000);
           client.setSoTimeout(120000);
           client.request(recoverRequestCmd);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/ZkController.java b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
index 81897b7..e288f5e 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -35,6 +35,7 @@ import java.util.concurrent.TimeoutException;
 import com.google.common.base.Strings;
 import org.apache.commons.lang.StringUtils;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.WaitForState;
 import org.apache.solr.cloud.overseer.OverseerAction;
 import org.apache.solr.cloud.overseer.SliceMutator;
@@ -1574,7 +1575,7 @@ public final class ZkController {
         log.info("Replica " + myCoreNodeName +
             " NOT in leader-initiated recovery, need to wait for leader to see down state.");
 
-        try (HttpSolrClient client = new HttpSolrClient(leaderBaseUrl)) {
+        try (HttpSolrClient client = new Builder(leaderBaseUrl).build()) {
           client.setConnectionTimeout(15000);
           client.setSoTimeout(120000);
           WaitForState prepCmd = new WaitForState();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java b/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java
index b8993da..2808906 100644
--- a/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java
+++ b/solr/core/src/java/org/apache/solr/cloud/rule/SnitchContext.java
@@ -105,7 +105,8 @@ public class SnitchContext implements RemoteCallback {
   public SimpleSolrResponse invoke(UpdateShardHandler shardHandler,  final String url, String path, SolrParams params)
       throws IOException, SolrServerException {
     GenericSolrRequest request = new GenericSolrRequest(SolrRequest.METHOD.GET, path, params);
-    try (HttpSolrClient client = new HttpSolrClient(url, shardHandler.getHttpClient(), new BinaryResponseParser())) {
+    try (HttpSolrClient client = new HttpSolrClient.Builder(url).withHttpClient(shardHandler.getHttpClient())
+        .withResponseParser(new BinaryResponseParser()).build()) {
       NamedList<Object> rsp = client.request(request);
       request.response.nl = rsp;
       return request.response;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorManager.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorManager.java b/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorManager.java
index 2822e60..af0161e 100644
--- a/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorManager.java
+++ b/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorManager.java
@@ -16,9 +16,16 @@
  */
 package org.apache.solr.handler;
 
+import java.io.IOException;
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.CommonParams;
@@ -30,12 +37,6 @@ import org.apache.solr.update.CdcrUpdateLog;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.io.IOException;
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-
 class CdcrReplicatorManager implements CdcrStateManager.CdcrStateObserver {
 
   private List<CdcrReplicatorState> replicatorStates;
@@ -64,7 +65,10 @@ class CdcrReplicatorManager implements CdcrStateManager.CdcrStateObserver {
         String zkHost = params.get(CdcrParams.ZK_HOST_PARAM);
         String targetCollection = params.get(CdcrParams.TARGET_COLLECTION_PARAM);
 
-        CloudSolrClient client = new CloudSolrClient(zkHost, true);
+        CloudSolrClient client = new Builder()
+            .withZkHost(zkHost)
+            .sendUpdatesOnlyToShardLeaders()
+            .build();
         client.setDefaultCollection(targetCollection);
         replicatorStates.add(new CdcrReplicatorState(targetCollection, zkHost, client));
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/CdcrRequestHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/CdcrRequestHandler.java b/solr/core/src/java/org/apache/solr/handler/CdcrRequestHandler.java
index 23e4aba..f60e562 100644
--- a/solr/core/src/java/org/apache/solr/handler/CdcrRequestHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/CdcrRequestHandler.java
@@ -595,7 +595,7 @@ public class CdcrRequestHandler extends RequestHandlerBase implements SolrCoreAw
 
     @Override
     public Long call() throws Exception {
-      try (HttpSolrClient server = new HttpSolrClient(baseUrl)) {
+      try (HttpSolrClient server = new HttpSolrClient.Builder(baseUrl).build()) {
         server.setConnectionTimeout(15000);
         server.setSoTimeout(60000);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/CdcrUpdateLogSynchronizer.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/CdcrUpdateLogSynchronizer.java b/solr/core/src/java/org/apache/solr/handler/CdcrUpdateLogSynchronizer.java
index 4955992..7071908 100644
--- a/solr/core/src/java/org/apache/solr/handler/CdcrUpdateLogSynchronizer.java
+++ b/solr/core/src/java/org/apache/solr/handler/CdcrUpdateLogSynchronizer.java
@@ -129,7 +129,7 @@ class CdcrUpdateLogSynchronizer implements CdcrStateManager.CdcrStateObserver {
           return;
         }
 
-        HttpSolrClient server = new HttpSolrClient(leaderUrl);
+        HttpSolrClient server = new HttpSolrClient.Builder(leaderUrl).build();
         server.setConnectionTimeout(15000);
         server.setSoTimeout(60000);
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
----------------------------------------------------------------------
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 7f38acd..71a2a84 100644
--- a/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
+++ b/solr/core/src/java/org/apache/solr/handler/IndexFetcher.java
@@ -68,6 +68,7 @@ import org.apache.lucene.store.IndexOutput;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
@@ -231,7 +232,7 @@ public class IndexFetcher {
     QueryRequest req = new QueryRequest(params);
 
     // TODO modify to use shardhandler
-    try (HttpSolrClient client = new HttpSolrClient(masterUrl, myHttpClient)) {
+    try (HttpSolrClient client = new Builder(masterUrl).withHttpClient(myHttpClient).build()) {
       client.setSoTimeout(soTimeout);
       client.setConnectionTimeout(connTimeout);
 
@@ -253,7 +254,7 @@ public class IndexFetcher {
     QueryRequest req = new QueryRequest(params);
 
     // TODO modify to use shardhandler
-    try (HttpSolrClient client = new HttpSolrClient(masterUrl, myHttpClient)) {
+    try (HttpSolrClient client = new HttpSolrClient.Builder(masterUrl).withHttpClient(myHttpClient).build()) {
       client.setSoTimeout(soTimeout);
       client.setConnectionTimeout(connTimeout);
       NamedList response = client.request(req);
@@ -1619,7 +1620,10 @@ public class IndexFetcher {
       InputStream is = null;
 
       // TODO use shardhandler
-      try (HttpSolrClient client = new HttpSolrClient(masterUrl, myHttpClient, null)) {
+      try (HttpSolrClient client = new Builder(masterUrl)
+          .withHttpClient(myHttpClient)
+          .withResponseParser(null)
+          .build()) {
         client.setSoTimeout(soTimeout);
         client.setConnectionTimeout(connTimeout);
         QueryRequest req = new QueryRequest(params);
@@ -1728,7 +1732,7 @@ public class IndexFetcher {
     params.set(CommonParams.QT, "/replication");
 
     // TODO use shardhandler
-    try (HttpSolrClient client = new HttpSolrClient(masterUrl, myHttpClient)) {
+    try (HttpSolrClient client = new HttpSolrClient.Builder(masterUrl).withHttpClient(myHttpClient).build()) {
       client.setSoTimeout(soTimeout);
       client.setConnectionTimeout(connTimeout);
       QueryRequest request = new QueryRequest(params);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
index eac9b11..9728597 100644
--- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
@@ -69,7 +69,6 @@ import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.schema.SchemaManager;
 import org.apache.solr.security.AuthorizationContext;
 import org.apache.solr.security.PermissionNameProvider;
-import org.apache.solr.security.PermissionNameProvider.Name;
 import org.apache.solr.util.CommandOperation;
 import org.apache.solr.util.DefaultSolrThreadFactory;
 import org.apache.solr.util.RTimer;
@@ -785,7 +784,7 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa
     public Boolean call() throws Exception {
       final RTimer timer = new RTimer();
       int attempts = 0;
-      try (HttpSolrClient solr = new HttpSolrClient(coreUrl)) {
+      try (HttpSolrClient solr = new HttpSolrClient.Builder(coreUrl).build()) {
         // eventually, this loop will get killed by the ExecutorService's timeout
         while (true) {
           try {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
index f0a332e..64b10ab 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
@@ -35,6 +35,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.RequestSyncShard;
 import org.apache.solr.client.solrj.response.RequestStatusState;
@@ -427,7 +428,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
         ZkNodeProps leaderProps = clusterState.getLeader(collection, shard);
         ZkCoreNodeProps nodeProps = new ZkCoreNodeProps(leaderProps);
 
-        try (HttpSolrClient client = new HttpSolrClient(nodeProps.getBaseUrl())) {
+        try (HttpSolrClient client = new Builder(nodeProps.getBaseUrl()).build()) {
           client.setConnectionTimeout(15000);
           client.setSoTimeout(60000);
           RequestSyncShard reqSyncShard = new CoreAdminRequest.RequestSyncShard();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
index 4ae013c..609e433 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
@@ -35,7 +35,7 @@ import org.apache.http.client.HttpClient;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrResponse;
-import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
 import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.util.ClientUtils;
@@ -54,7 +54,6 @@ import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.core.CoreDescriptor;
-import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -192,7 +191,7 @@ public class HttpShardHandler extends ShardHandler {
         if (urls.size() <= 1) {
           String url = urls.get(0);
           srsp.setShardAddress(url);
-          try (SolrClient client = new HttpSolrClient(url, httpClient)) {
+          try (SolrClient client = new Builder(url).withHttpClient(httpClient).build()) {
             ssr.nl = client.request(req);
           }
         } else {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandlerFactory.java
----------------------------------------------------------------------
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 0412838..bc5927f 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
@@ -22,6 +22,7 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.LBHttpSolrClient;
+import org.apache.solr.client.solrj.impl.LBHttpSolrClient.Builder;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.ExecutorUtil;
@@ -177,7 +178,9 @@ public class HttpShardHandlerFactory extends ShardHandlerFactory implements org.
   }
 
   protected LBHttpSolrClient createLoadbalancer(HttpClient httpClient){
-    LBHttpSolrClient client = new LBHttpSolrClient(httpClient);
+    LBHttpSolrClient client = new Builder()
+        .withHttpClient(httpClient)
+        .build();
     client.setConnectionTimeout(connectionTimeout);
     client.setSoTimeout(soTimeout);
     return client;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/handler/component/IterativeMergeStrategy.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/component/IterativeMergeStrategy.java b/solr/core/src/java/org/apache/solr/handler/component/IterativeMergeStrategy.java
index 83677e4..2138948 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/IterativeMergeStrategy.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/IterativeMergeStrategy.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.common.SolrDocumentList;
@@ -81,7 +82,9 @@ public abstract class IterativeMergeStrategy implements MergeStrategy  {
 
     public CallBack(ShardResponse originalShardResponse, QueryRequest req) {
 
-      this.solrClient = new HttpSolrClient(originalShardResponse.getShardAddress(), getHttpClient());
+      this.solrClient = new Builder(originalShardResponse.getShardAddress())
+          .withHttpClient(getHttpClient())
+          .build();
       this.req = req;
       this.originalShardResponse = originalShardResponse;
       req.setMethod(SolrRequest.METHOD.POST);
@@ -129,4 +132,4 @@ public abstract class IterativeMergeStrategy implements MergeStrategy  {
         return httpClient;
       }
   }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java b/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
index 953a635..b22feab 100644
--- a/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
@@ -326,7 +326,7 @@ public final class ManagedIndexSchema extends IndexSchema {
     @Override
     public Integer call() throws Exception {
       int remoteVersion = -1;
-      try (HttpSolrClient solr = new HttpSolrClient(coreUrl)) {
+      try (HttpSolrClient solr = new HttpSolrClient.Builder(coreUrl).build()) {
         // eventually, this loop will get killed by the ExecutorService's timeout
         while (remoteVersion == -1 || remoteVersion < expectedZkVersion) {
           try {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java b/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
index 9a196b7..c161b82 100644
--- a/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
+++ b/solr/core/src/java/org/apache/solr/update/SolrCmdDistributor.java
@@ -44,7 +44,6 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
-import java.util.concurrent.Callable;
 import java.util.concurrent.CompletionService;
 import java.util.concurrent.ExecutorCompletionService;
 import java.util.concurrent.ExecutorService;
@@ -260,7 +259,7 @@ public class SolrCmdDistributor {
     if (req.synchronous) {
       blockAndDoRetries();
 
-      try (HttpSolrClient client = new HttpSolrClient(req.node.getUrl(), clients.getHttpClient())) {
+      try (HttpSolrClient client = new HttpSolrClient.Builder(req.node.getUrl()).withHttpClient(clients.getHttpClient()).build()) {
         client.request(req.uReq);
       } catch (Exception e) {
         throw new SolrException(ErrorCode.SERVER_ERROR, "Failed synchronous update on shard " + req.node + " update: " + req.uReq , e);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java b/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java
index ecc2a2b..fc50be2 100644
--- a/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java
+++ b/solr/core/src/java/org/apache/solr/update/StreamingSolrClients.java
@@ -16,6 +16,16 @@
  */
 package org.apache.solr.update;
 
+import java.lang.invoke.MethodHandles;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
 import org.apache.http.HttpResponse;
 import org.apache.http.client.HttpClient;
 import org.apache.solr.client.solrj.SolrClient;
@@ -29,16 +39,6 @@ import org.apache.solr.update.processor.DistributingUpdateProcessorFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutorService;
-
 public class StreamingSolrClients {
   private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
 
@@ -72,24 +72,7 @@ public class StreamingSolrClients {
       // NOTE: increasing to more than 1 threadCount for the client could cause updates to be reordered
       // on a greater scale since the current behavior is to only increase the number of connections/Runners when
       // the queue is more than half full.
-      client = new ConcurrentUpdateSolrClient(url, httpClient, 100, runnerCount, updateExecutor, true) {
-        @Override
-        public void handleError(Throwable ex) {
-          req.trackRequestResult(null, false);
-          log.error("error", ex);
-          Error error = new Error();
-          error.e = (Exception) ex;
-          if (ex instanceof SolrException) {
-            error.statusCode = ((SolrException) ex).code();
-          }
-          error.req = req;
-          errors.add(error);
-        }
-        @Override
-        public void onSuccess(HttpResponse resp) {
-          req.trackRequestResult(resp, true);
-        }
-      };
+      client = new ErrorReportingConcurrentUpdateSolrClient(url, httpClient, 100, runnerCount, updateExecutor, true, req);
       client.setParser(new BinaryResponseParser());
       client.setRequestWriter(new BinaryRequestWriter());
       client.setPollQueueTime(req.pollQueueTime);
@@ -132,4 +115,31 @@ public class StreamingSolrClients {
   public ExecutorService getUpdateExecutor() {
     return updateExecutor;
   }
+  
+  class ErrorReportingConcurrentUpdateSolrClient extends ConcurrentUpdateSolrClient {
+    private final SolrCmdDistributor.Req req;
+    
+    public ErrorReportingConcurrentUpdateSolrClient(String solrServerUrl, HttpClient client, int queueSize,
+        int threadCount, ExecutorService es, boolean streamDeletes, SolrCmdDistributor.Req req) {
+      super(solrServerUrl, client, queueSize, threadCount, es, streamDeletes);
+      this.req = req;
+    }
+    
+    @Override
+    public void handleError(Throwable ex) {
+      req.trackRequestResult(null, false);
+      log.error("error", ex);
+      Error error = new Error();
+      error.e = (Exception) ex;
+      if (ex instanceof SolrException) {
+        error.statusCode = ((SolrException) ex).code();
+      }
+      error.req = req;
+      errors.add(error);
+    }
+    @Override
+    public void onSuccess(HttpResponse resp) {
+      req.trackRequestResult(resp, true);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/java/org/apache/solr/util/SolrCLI.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/util/SolrCLI.java b/solr/core/src/java/org/apache/solr/util/SolrCLI.java
index ae11118..5804b5d 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrCLI.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrCLI.java
@@ -82,6 +82,7 @@ import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
+import org.apache.solr.client.solrj.impl.HttpSolrClient.Builder;
 import org.apache.solr.client.solrj.impl.SolrHttpClientBuilder;
 import org.apache.solr.client.solrj.request.ContentStreamUpdateRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -209,7 +210,7 @@ public class SolrCLI {
       String zkHost = cli.getOptionValue("zkHost", ZK_HOST);
       
       log.debug("Connecting to Solr cluster: " + zkHost);
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost)) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
 
         String collection = cli.getOptionValue("collection");
         if (collection != null)
@@ -1162,7 +1163,7 @@ public class SolrCLI {
             q = new SolrQuery("*:*");
             q.setRows(0);
             q.set("distrib", "false");
-            try (HttpSolrClient solr = new HttpSolrClient(coreUrl)) {
+            try (HttpSolrClient solr = new HttpSolrClient.Builder(coreUrl).build()) {
 
               String solrUrl = solr.getBaseURL();
 
@@ -1285,7 +1286,7 @@ public class SolrCLI {
       if (zkHost == null)
         throw new IllegalStateException("Must provide either the '-solrUrl' or '-zkHost' parameters!");
 
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost)) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
         cloudSolrClient.connect();
         Set<String> liveNodes = cloudSolrClient.getZkStateReader().getClusterState().getLiveNodes();
         if (liveNodes.isEmpty())
@@ -1398,7 +1399,7 @@ public class SolrCLI {
             "create_collection can only be used when running in SolrCloud mode.\n");
       }
 
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost)) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
         echo("\nConnecting to ZooKeeper at " + zkHost+" ...");
         cloudSolrClient.connect();
         runCloudTool(cloudSolrClient, cli);
@@ -1707,7 +1708,7 @@ public class SolrCLI {
             " is running in standalone server mode, upconfig can only be used when running in SolrCloud mode.\n");
       }
 
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost)) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
         echo("\nConnecting to ZooKeeper at " + zkHost + " ...");
         cloudSolrClient.connect();
         upconfig(cloudSolrClient, cli, cli.getOptionValue("confname"), cli.getOptionValue("confdir"));
@@ -1762,7 +1763,7 @@ public class SolrCLI {
       }
 
 
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost)) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
         echo("\nConnecting to ZooKeeper at " + zkHost + " ...");
         cloudSolrClient.connect();
         downconfig(cloudSolrClient, cli.getOptionValue("confname"), cli.getOptionValue("confdir"));
@@ -1853,7 +1854,7 @@ public class SolrCLI {
 
     protected void deleteCollection(CommandLine cli) throws Exception {
       String zkHost = getZkHost(cli);
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient(zkHost)) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
         echo("Connecting to ZooKeeper at " + zkHost);
         cloudSolrClient.connect();
         deleteCollection(cloudSolrClient, cli);
@@ -2030,7 +2031,7 @@ public class SolrCLI {
       echo("\nPOSTing request to Config API: " + solrUrl + updatePath);
       echo(jsonBody);
 
-      try (SolrClient solrClient = new HttpSolrClient(solrUrl)) {
+      try (SolrClient solrClient = new Builder(solrUrl).build()) {
         NamedList<Object> result = postJsonToSolr(solrClient, updatePath, jsonBody);
         Integer statusCode = (Integer)((NamedList)result.get("responseHeader")).get("status");
         if (statusCode == 0) {
@@ -2425,7 +2426,9 @@ public class SolrCLI {
     protected void waitToSeeLiveNodes(int maxWaitSecs, String zkHost, int numNodes) {
       CloudSolrClient cloudClient = null;
       try {
-        cloudClient = new CloudSolrClient(zkHost);
+        cloudClient = new CloudSolrClient.Builder()
+            .withZkHost(zkHost)
+            .build();
         cloudClient.connect();
         Set<String> liveNodes = cloudClient.getZkStateReader().getClusterState().getLiveNodes();
         int numLiveNodes = (liveNodes != null) ? liveNodes.size() : 0;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/TestTolerantSearch.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/TestTolerantSearch.java b/solr/core/src/test/org/apache/solr/TestTolerantSearch.java
index 1d7dd2b..cb485d0 100644
--- a/solr/core/src/test/org/apache/solr/TestTolerantSearch.java
+++ b/solr/core/src/test/org/apache/solr/TestTolerantSearch.java
@@ -59,8 +59,8 @@ public class TestTolerantSearch extends SolrJettyTestBase {
     solrHome = createSolrHome();
     createJetty(solrHome.getAbsolutePath());
     String url = jetty.getBaseUrl().toString();
-    collection1 = new HttpSolrClient(url + "/collection1");
-    collection2 = new HttpSolrClient(url + "/collection2");
+    collection1 = getHttpSolrClient(url + "/collection1");
+    collection2 = getHttpSolrClient(url + "/collection2");
     
     String urlCollection1 = jetty.getBaseUrl().toString() + "/" + "collection1";
     String urlCollection2 = jetty.getBaseUrl().toString() + "/" + "collection2";
@@ -68,7 +68,7 @@ public class TestTolerantSearch extends SolrJettyTestBase {
     shard2 = urlCollection2.replaceAll("https?://", "");
     
     //create second core
-    try (HttpSolrClient nodeClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient nodeClient = getHttpSolrClient(url)) {
       CoreAdminRequest.Create req = new CoreAdminRequest.Create();
       req.setCoreName("collection2");
       req.setConfigSet("collection1");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/client/solrj/ConnectionReuseTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/client/solrj/ConnectionReuseTest.java b/solr/core/src/test/org/apache/solr/client/solrj/ConnectionReuseTest.java
index 0d78975..cc998b4 100644
--- a/solr/core/src/test/org/apache/solr/client/solrj/ConnectionReuseTest.java
+++ b/solr/core/src/test/org/apache/solr/client/solrj/ConnectionReuseTest.java
@@ -83,12 +83,12 @@ public class ConnectionReuseTest extends AbstractFullDistribZkTestBase {
     try {
       int rndClient = random().nextInt(3);
       if (rndClient == 0) {
-        client = new ConcurrentUpdateSolrClient(url.toString(), httpClient, 6, 1); // currently only testing with 1
+        client = getConcurrentUpdateSolrClient(url.toString(), httpClient, 6, 1); // currently only testing with 1
                                                                                    // thread
       } else if (rndClient == 1) {
-        client = new HttpSolrClient(url.toString(), httpClient);
+        client = getHttpSolrClient(url.toString(), httpClient);
       } else if (rndClient == 2) {
-        client = new CloudSolrClient(zkServer.getZkAddress(), random().nextBoolean(), httpClient);
+        client = getCloudSolrClient(zkServer.getZkAddress(), random().nextBoolean(), httpClient);
         ((CloudSolrClient) client).setParallelUpdates(random().nextBoolean());
         ((CloudSolrClient) client).setDefaultCollection(DEFAULT_COLLECTION);
         ((CloudSolrClient) client).getLbClient().setConnectionTimeout(30000);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestJettySolrRunner.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestJettySolrRunner.java b/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestJettySolrRunner.java
index dc8896d..9ded73b 100644
--- a/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestJettySolrRunner.java
+++ b/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestJettySolrRunner.java
@@ -19,7 +19,6 @@ package org.apache.solr.client.solrj.embedded;
 import com.google.common.base.Charsets;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrClient;
-import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
 import org.junit.Test;
 
@@ -53,7 +52,7 @@ public class TestJettySolrRunner extends SolrTestCaseJ4 {
     try {
       runner.start();
 
-      try (SolrClient client = new HttpSolrClient(runner.getBaseUrl().toString())) {
+      try (SolrClient client = getHttpSolrClient(runner.getBaseUrl().toString())) {
         CoreAdminRequest.Create createReq = new CoreAdminRequest.Create();
         createReq.setCoreName("newcore");
         createReq.setConfigSet("minimal");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
index a270a10..fa3f861 100644
--- a/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/AliasIntegrationTest.java
@@ -119,7 +119,7 @@ public class AliasIntegrationTest extends AbstractFullDistribZkTestBase {
     query.set("collection", "testalias");
     JettySolrRunner jetty = jettys.get(random().nextInt(jettys.size()));
     int port = jetty.getLocalPort();
-    try (HttpSolrClient client = new HttpSolrClient(buildUrl(port) + "/testalias")) {
+    try (HttpSolrClient client = getHttpSolrClient(buildUrl(port) + "/testalias")) {
       res = client.query(query);
       assertEquals(3, res.getResults().getNumFound());
     }
@@ -128,7 +128,7 @@ public class AliasIntegrationTest extends AbstractFullDistribZkTestBase {
     query = new SolrQuery("*:*");
     jetty = jettys.get(random().nextInt(jettys.size()));
     port = jetty.getLocalPort();
-    try (HttpSolrClient client = new HttpSolrClient(buildUrl(port) + "/testalias")) {
+    try (HttpSolrClient client = getHttpSolrClient(buildUrl(port) + "/testalias")) {
       res = client.query(query);
       assertEquals(3, res.getResults().getNumFound());
     }
@@ -136,7 +136,7 @@ public class AliasIntegrationTest extends AbstractFullDistribZkTestBase {
     createAlias("testalias", "collection2,collection1");
     
     // search with new cloud client
-    try (CloudSolrClient cloudSolrClient = new CloudSolrClient(zkServer.getZkAddress(), random().nextBoolean())) {
+    try (CloudSolrClient cloudSolrClient = getCloudSolrClient(zkServer.getZkAddress(), random().nextBoolean())) {
       cloudSolrClient.setParallelUpdates(random().nextBoolean());
       query = new SolrQuery("*:*");
       query.set("collection", "testalias");
@@ -155,7 +155,7 @@ public class AliasIntegrationTest extends AbstractFullDistribZkTestBase {
     query.set("collection", "testalias");
     jetty = jettys.get(random().nextInt(jettys.size()));
     port = jetty.getLocalPort();
-    try (HttpSolrClient client = new HttpSolrClient(buildUrl(port) + "/testalias")) {
+    try (HttpSolrClient client = getHttpSolrClient(buildUrl(port) + "/testalias")) {
       res = client.query(query);
       assertEquals(5, res.getResults().getNumFound());
     }
@@ -163,7 +163,7 @@ public class AliasIntegrationTest extends AbstractFullDistribZkTestBase {
     query = new SolrQuery("*:*");
     jetty = jettys.get(random().nextInt(jettys.size()));
     port = jetty.getLocalPort();
-    try (HttpSolrClient client = new HttpSolrClient(buildUrl(port) + "/testalias")) {
+    try (HttpSolrClient client = getHttpSolrClient(buildUrl(port) + "/testalias")) {
       res = client.query(query);
       assertEquals(5, res.getResults().getNumFound());
     }
@@ -190,7 +190,7 @@ public class AliasIntegrationTest extends AbstractFullDistribZkTestBase {
     // try a std client
     // search 1 and 2, but have no collections param
     query = new SolrQuery("*:*");
-    try (HttpSolrClient client = new HttpSolrClient(getBaseUrl((HttpSolrClient) clients.get(0)) + "/testalias")) {
+    try (HttpSolrClient client = getHttpSolrClient(getBaseUrl((HttpSolrClient) clients.get(0)) + "/testalias")) {
       res = client.query(query);
       assertEquals(5, res.getResults().getNumFound());
     }
@@ -200,7 +200,7 @@ public class AliasIntegrationTest extends AbstractFullDistribZkTestBase {
     // a second alias
     createAlias("testalias2", "collection2");
 
-    try (HttpSolrClient client = new HttpSolrClient(getBaseUrl((HttpSolrClient) clients.get(0)) + "/testalias")) {
+    try (HttpSolrClient client = getHttpSolrClient(getBaseUrl((HttpSolrClient) clients.get(0)) + "/testalias")) {
       SolrInputDocument doc8 = getDoc(id, 11, i1, -600, tlong, 600, t1,
           "humpty dumpy4 sat on a walls");
       client.add(doc8);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/AsyncMigrateRouteKeyTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/AsyncMigrateRouteKeyTest.java b/solr/core/src/test/org/apache/solr/cloud/AsyncMigrateRouteKeyTest.java
index b9e6d3a..7c71a92 100644
--- a/solr/core/src/test/org/apache/solr/cloud/AsyncMigrateRouteKeyTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/AsyncMigrateRouteKeyTest.java
@@ -113,7 +113,7 @@ public class AsyncMigrateRouteKeyTest extends MigrateRouteKeyTest {
     String baseUrl = ((HttpSolrClient) shardToJetty.get(SHARD1).get(0).client.solrClient).getBaseURL();
     baseUrl = baseUrl.substring(0, baseUrl.length() - "collection1".length());
 
-    try (HttpSolrClient baseServer = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient baseServer = getHttpSolrClient(baseUrl)) {
       baseServer.setConnectionTimeout(15000);
       return baseServer.request(request);
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/BaseCdcrDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/BaseCdcrDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/BaseCdcrDistributedZkTest.java
index ca4f912..e262d25 100644
--- a/solr/core/src/test/org/apache/solr/cloud/BaseCdcrDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/BaseCdcrDistributedZkTest.java
@@ -177,7 +177,7 @@ public class BaseCdcrDistributedZkTest extends AbstractDistribZkTestBase {
   }
 
   protected CloudSolrClient createCloudClient(String defaultCollection) {
-    CloudSolrClient server = new CloudSolrClient(zkServer.getZkAddress(), random().nextBoolean());
+    CloudSolrClient server = getCloudSolrClient(zkServer.getZkAddress(), random().nextBoolean());
     server.setParallelUpdates(random().nextBoolean());
     if (defaultCollection != null) server.setDefaultCollection(defaultCollection);
     return server;
@@ -748,7 +748,7 @@ public class BaseCdcrDistributedZkTest extends AbstractDistribZkTestBase {
   protected static SolrClient createNewSolrServer(String baseUrl) {
     try {
       // setup the server...
-      HttpSolrClient s = new HttpSolrClient(baseUrl);
+      HttpSolrClient s = getHttpSolrClient(baseUrl);
       s.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
       return s;
     } catch (Exception ex) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java
index a042501..61b9901 100644
--- a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java
+++ b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZk2Test.java
@@ -147,7 +147,7 @@ public class BasicDistributedZk2Test extends AbstractFullDistribZkTestBase {
   
   private void testNodeWithoutCollectionForwarding() throws Exception {
     final String baseUrl = getBaseUrl((HttpSolrClient) clients.get(0));
-    try (HttpSolrClient client = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient client = getHttpSolrClient(baseUrl)) {
       client.setConnectionTimeout(30000);
       Create createCmd = new Create();
       createCmd.setRoles("none");
@@ -180,7 +180,7 @@ public class BasicDistributedZk2Test extends AbstractFullDistribZkTestBase {
 
     SolrQuery query = new SolrQuery("*:*");
 
-    try (HttpSolrClient qclient = new HttpSolrClient(baseUrl + "/onenodecollection" + "core")) {
+    try (HttpSolrClient qclient = getHttpSolrClient(baseUrl + "/onenodecollection" + "core")) {
 
       // it might take a moment for the proxy node to see us in their cloud state
       waitForNon403or404or503(qclient);
@@ -196,7 +196,7 @@ public class BasicDistributedZk2Test extends AbstractFullDistribZkTestBase {
       assertEquals(docs - 1, results.getResults().getNumFound());
     }
     
-    try (HttpSolrClient qclient = new HttpSolrClient(baseUrl + "/onenodecollection")) {
+    try (HttpSolrClient qclient = getHttpSolrClient(baseUrl + "/onenodecollection")) {
       QueryResponse results = qclient.query(query);
       assertEquals(docs - 1, results.getResults().getNumFound());
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
index b17f9b0..17ddca4 100644
--- a/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/BasicDistributedZkTest.java
@@ -404,7 +404,7 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
     for (Slice slice : dColl.getActiveSlices()) {
       long sliceDocCount = -1;
       for (Replica rep : slice.getReplicas()) {
-        try (HttpSolrClient one = new HttpSolrClient(rep.getCoreUrl())) {
+        try (HttpSolrClient one = getHttpSolrClient(rep.getCoreUrl())) {
           SolrQuery query = new SolrQuery("*:*");
           query.setDistrib(false);
           QueryResponse resp = one.query(query);
@@ -529,7 +529,7 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
   private void testStopAndStartCoresInOneInstance() throws Exception {
     SolrClient client = clients.get(0);
     String url3 = getBaseUrl(client);
-    try (final HttpSolrClient httpSolrClient = new HttpSolrClient(url3)) {
+    try (final HttpSolrClient httpSolrClient = getHttpSolrClient(url3)) {
       httpSolrClient.setConnectionTimeout(15000);
       httpSolrClient.setSoTimeout(60000);
       ThreadPoolExecutor executor = null;
@@ -750,7 +750,7 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
 
   private Long getNumCommits(HttpSolrClient sourceClient) throws
       SolrServerException, IOException {
-    try (HttpSolrClient client = new HttpSolrClient(sourceClient.getBaseURL())) {
+    try (HttpSolrClient client = getHttpSolrClient(sourceClient.getBaseURL())) {
       client.setConnectionTimeout(15000);
       client.setSoTimeout(60000);
       ModifiableSolrParams params = new ModifiableSolrParams();
@@ -841,7 +841,7 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
     ZkCoreNodeProps props = new ZkCoreNodeProps(getCommonCloudSolrClient().getZkStateReader().getClusterState().getLeader(oneInstanceCollection2, "slice1"));
     
     // now test that unloading a core gets us a new leader
-    try (HttpSolrClient unloadClient = new HttpSolrClient(baseUrl)) {
+    try (HttpSolrClient unloadClient = getHttpSolrClient(baseUrl)) {
       unloadClient.setConnectionTimeout(15000);
       unloadClient.setSoTimeout(60000);
       Unload unloadCmd = new Unload(true);
@@ -961,7 +961,7 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
       List<SolrClient> collectionClients, final String baseUrl, final int num,
       final String shardId) {
     Callable call = () -> {
-      try (HttpSolrClient client = new HttpSolrClient(baseUrl)) {
+      try (HttpSolrClient client = getHttpSolrClient(baseUrl)) {
         // client.setConnectionTimeout(15000);
         Create createCmd = new Create();
         createCmd.setRoles("none");
@@ -1090,7 +1090,7 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
       final int frozeUnique = unique;
       Callable call = () -> {
 
-        try (HttpSolrClient client1 = new HttpSolrClient(baseUrl)) {
+        try (HttpSolrClient client1 = getHttpSolrClient(baseUrl)) {
           client1.setConnectionTimeout(15000);
           client1.setSoTimeout(60000);
           Create createCmd = new Create();
@@ -1118,7 +1118,7 @@ public class BasicDistributedZkTest extends AbstractFullDistribZkTestBase {
   protected SolrClient createNewSolrClient(String collection, String baseUrl) {
     try {
       // setup the server...
-      HttpSolrClient client = new HttpSolrClient(baseUrl + "/" + collection);
+      HttpSolrClient client = getHttpSolrClient(baseUrl + "/" + collection);
 
       return client;
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java
index 3ddf99d..58d52d2 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ChaosMonkeyNothingIsSafeTest.java
@@ -16,7 +16,15 @@
  */
 package org.apache.solr.cloud;
 
-import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering;
+import java.lang.invoke.MethodHandles;
+import java.net.ConnectException;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.http.client.HttpClient;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.lucene.util.LuceneTestCase.Slow;
 import org.apache.solr.SolrTestCaseJ4.SuppressObjectReleaseTracker;
@@ -36,13 +44,7 @@ import org.junit.Test;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.lang.invoke.MethodHandles;
-import java.net.ConnectException;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicInteger;
+import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering;
 
 @Slow
 @SuppressSSL(bugUrl = "https://issues.apache.org/jira/browse/SOLR-5776")
@@ -297,14 +299,7 @@ public class ChaosMonkeyNothingIsSafeTest extends AbstractFullDistribZkTestBase
       setDaemon(true);
       this.clients = clients;
 
-      cusc = new ConcurrentUpdateSolrClient(
-          ((HttpSolrClient) clients.get(0)).getBaseURL(), httpClient, 8,
-          2) {
-        @Override
-        public void handleError(Throwable ex) {
-          log.warn("cusc error", ex);
-        }
-      };
+      cusc = new ErrorLoggingConcurrentUpdateSolrClient(((HttpSolrClient) clients.get(0)).getBaseURL(), httpClient, 8, 2);
       cusc.setConnectionTimeout(10000);
       cusc.setSoTimeout(clientSoTimeout);
     }
@@ -363,14 +358,8 @@ public class ChaosMonkeyNothingIsSafeTest extends AbstractFullDistribZkTestBase
           clientIndex = 0;
         }
         cusc.shutdownNow();
-        cusc = new ConcurrentUpdateSolrClient(
-            ((HttpSolrClient) clients.get(clientIndex)).getBaseURL(),
-            httpClient, 30, 3) {
-          @Override
-          public void handleError(Throwable ex) {
-            log.warn("cusc error", ex);
-          }
-        };
+        cusc = new ErrorLoggingConcurrentUpdateSolrClient(((HttpSolrClient) clients.get(clientIndex)).getBaseURL(),
+            httpClient, 30, 3);
       }
     }
     
@@ -407,4 +396,13 @@ public class ChaosMonkeyNothingIsSafeTest extends AbstractFullDistribZkTestBase
     indexDoc(doc);
   }
   
+  class ErrorLoggingConcurrentUpdateSolrClient extends ConcurrentUpdateSolrClient {
+    public ErrorLoggingConcurrentUpdateSolrClient(String serverUrl, HttpClient httpClient, int queueSize, int threadCount) {
+      super(serverUrl, httpClient, queueSize, threadCount, null, false);
+    }
+    @Override
+    public void handleError(Throwable ex) {
+      log.warn("cusc error", ex);
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/CollectionReloadTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionReloadTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionReloadTest.java
index 65ff78b..cf8a650 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionReloadTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionReloadTest.java
@@ -131,7 +131,7 @@ public class CollectionReloadTest extends AbstractFullDistribZkTestBase {
     ZkCoreNodeProps coreProps = new ZkCoreNodeProps(replica);
     String coreName = coreProps.getCoreName();
     boolean reloadedOk = false;
-    try (HttpSolrClient client = new HttpSolrClient(coreProps.getBaseUrl())) {
+    try (HttpSolrClient client = getHttpSolrClient(coreProps.getBaseUrl())) {
       CoreAdminResponse statusResp = CoreAdminRequest.getStatus(coreName, client);
       long leaderCoreStartTime = statusResp.getStartTime(coreName).getTime();
 

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
index 5c80f2d..ad6df12 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPIDistributedZkTest.java
@@ -723,7 +723,7 @@ public class CollectionsAPIDistributedZkTest extends AbstractFullDistribZkTestBa
       
       String url = getUrlFromZk(collection);
 
-      try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+      try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
         // poll for a second - it can take a moment before we are ready to serve
         waitForNon403or404or503(collectionClient);
       }
@@ -743,7 +743,7 @@ public class CollectionsAPIDistributedZkTest extends AbstractFullDistribZkTestBa
         
         String url = getUrlFromZk(collection);
         
-        try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+        try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
           // poll for a second - it can take a moment before we are ready to serve
           waitForNon403or404or503(collectionClient);
         }
@@ -790,7 +790,7 @@ public class CollectionsAPIDistributedZkTest extends AbstractFullDistribZkTestBa
     
     String url = getUrlFromZk(collectionName);
 
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
 
       // lets try and use the solrj client to index a couple documents
       SolrInputDocument doc1 = getDoc(id, 6, i1, -600, tlong, 600, t1,
@@ -887,7 +887,7 @@ public class CollectionsAPIDistributedZkTest extends AbstractFullDistribZkTestBa
     
     url = getUrlFromZk(collectionName);
     
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
       // poll for a second - it can take a moment before we are ready to serve
       waitForNon403or404or503(collectionClient);
     }
@@ -1062,7 +1062,7 @@ public class CollectionsAPIDistributedZkTest extends AbstractFullDistribZkTestBa
           Entry<String,Replica> shardEntry = shardIt.next();
           ZkCoreNodeProps coreProps = new ZkCoreNodeProps(shardEntry.getValue());
           CoreAdminResponse mcr;
-          try (HttpSolrClient server = new HttpSolrClient(coreProps.getBaseUrl())) {
+          try (HttpSolrClient server = getHttpSolrClient(coreProps.getBaseUrl())) {
             mcr = CoreAdminRequest.getStatus(coreProps.getCoreName(), server);
           }
           long before = mcr.getStartTime(coreProps.getCoreName()).getTime();
@@ -1197,7 +1197,7 @@ public class CollectionsAPIDistributedZkTest extends AbstractFullDistribZkTestBa
           null, client, props);
       assertNotNull(newReplica);
 
-      try (HttpSolrClient coreclient = new HttpSolrClient(newReplica.getStr(ZkStateReader.BASE_URL_PROP))) {
+      try (HttpSolrClient coreclient = getHttpSolrClient(newReplica.getStr(ZkStateReader.BASE_URL_PROP))) {
         CoreAdminResponse status = CoreAdminRequest.getStatus(newReplica.getStr("core"), coreclient);
         NamedList<Object> coreStatus = status.getCoreStatus(newReplica.getStr("core"));
         String instanceDirStr = (String) coreStatus.get("instanceDir");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
index 6b0db0f..52ae96f 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CollectionsAPISolrJTest.java
@@ -257,7 +257,7 @@ public class CollectionsAPISolrJTest extends AbstractFullDistribZkTestBase {
 
     Replica replica1 = testCollection.getReplica("core_node1");
 
-    try (HttpSolrClient client = new HttpSolrClient(replica1.getStr("base_url"))) {
+    try (HttpSolrClient client = getHttpSolrClient(replica1.getStr("base_url"))) {
       CoreAdminResponse status = CoreAdminRequest.getStatus(replica1.getStr("core"), client);
       NamedList<Object> coreStatus = status.getCoreStatus(replica1.getStr("core"));
       String dataDirStr = (String) coreStatus.get("dataDir");

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java b/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java
index 82bf9d4..c8e30eb 100644
--- a/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/ConcurrentDeleteAndCreateCollectionTest.java
@@ -60,7 +60,8 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
     for (int i = 0; i < threads.length; i++) {
       final String collectionName = "collection" + i;
       uploadConfig(configDir, collectionName);
-      final SolrClient solrClient = new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+      final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+      final SolrClient solrClient = getHttpSolrClient(baseUrl);
       threads[i] = new CreateDeleteSearchCollectionThread("create-delete-search-" + i, collectionName, collectionName, 
           timeToRunSec, solrClient, failure);
     }
@@ -75,7 +76,8 @@ public class ConcurrentDeleteAndCreateCollectionTest extends SolrTestCaseJ4 {
     final String configName = "testconfig";
     final File configDir = getFile("solr").toPath().resolve("configsets/configset-2/conf").toFile();
     uploadConfig(configDir, configName); // upload config once, to be used by all collections
-    final SolrClient solrClient = new HttpSolrClient(solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString());
+    final String baseUrl = solrCluster.getJettySolrRunners().get(0).getBaseUrl().toString();
+    final SolrClient solrClient = getHttpSolrClient(baseUrl);
     final AtomicReference<Exception> failure = new AtomicReference<>();
     final int timeToRunSec = 30;
     final Thread[] threads = new Thread[2];

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/b02b026b/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java b/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java
index 0951b5d..0873fa3 100644
--- a/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/CustomCollectionTest.java
@@ -167,7 +167,7 @@ public class CustomCollectionTest extends AbstractFullDistribZkTestBase {
 
       String url = getUrlFromZk(getCommonCloudSolrClient().getZkStateReader().getClusterState(), collection);
 
-      try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+      try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
         // poll for a second - it can take a moment before we are ready to serve
         waitForNon403or404or503(collectionClient);
       }
@@ -195,7 +195,7 @@ public class CustomCollectionTest extends AbstractFullDistribZkTestBase {
     String url = getUrlFromZk(getCommonCloudSolrClient().getZkStateReader().getClusterState(), collectionName);
 
     String shard_fld = "shard_s";
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
 
       // lets try and use the solrj client to index a couple documents
   
@@ -292,12 +292,12 @@ public class CustomCollectionTest extends AbstractFullDistribZkTestBase {
       url = getUrlFromZk(getCommonCloudSolrClient().getZkStateReader().getClusterState(), collectionName);
     }
 
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
          // poll for a second - it can take a moment before we are ready to serve
       waitForNon403or404or503(collectionClient);
     }
 
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
       // lets try and use the solrj client to index a couple documents
   
       collectionClient.add(getDoc(id, 6, i1, -600, tlong, 600, t1,
@@ -343,13 +343,13 @@ public class CustomCollectionTest extends AbstractFullDistribZkTestBase {
 
     String url = getUrlFromZk(getCommonCloudSolrClient().getZkStateReader().getClusterState(), collectionName);
 
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
       // poll for a second - it can take a moment before we are ready to serve
       waitForNon403or404or503(collectionClient);
     }
 
 
-    try (HttpSolrClient collectionClient = new HttpSolrClient(url)) {
+    try (HttpSolrClient collectionClient = getHttpSolrClient(url)) {
       // lets try and use the solrj client to index a couple documents
   
       collectionClient.add(getDoc(id, 6, i1, -600, tlong, 600, t1,