You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ge...@apache.org on 2018/03/10 16:12:07 UTC

lucene-solr:branch_7x: SOLR-11629: Add new CloudSolrClient.Builder ctors

Repository: lucene-solr
Updated Branches:
  refs/heads/branch_7x 9341be837 -> 1d55336d0


SOLR-11629: Add new CloudSolrClient.Builder ctors

CloudSolrClient.Builder can be pointed at a Solr cluster in two ways: a
ZK connection string, or one or more Solr base URLs.  One of these two
values must be provided to create a working CloudSolrClient.

Since these values are required, this commit introduces two new ctors,
one for each means of CloudSolrClient setup.  It deprecates the existing
no-arg CloudSolrClient ctor.

Together, these changes make it clearer to our users that these options
are required (and mutually exclusive).


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

Branch: refs/heads/branch_7x
Commit: 1d55336d0f50ddc4fcbabfa94b62a8cebb285306
Parents: 9341be8
Author: Jason Gerlowski <ge...@apache.org>
Authored: Sat Mar 10 09:30:57 2018 -0500
Committer: Jason Gerlowski <ge...@apache.org>
Committed: Sat Mar 10 11:04:19 2018 -0500

----------------------------------------------------------------------
 solr/CHANGES.txt                                |  2 +
 .../stream/AnalyticsShardRequestManager.java    |  5 +-
 .../org/apache/solr/cloud/ZkController.java     |  6 +-
 .../solr/core/snapshots/SolrSnapshotsTool.java  |  3 +-
 .../solr/handler/CdcrReplicatorManager.java     |  5 +-
 .../admin/AutoscalingHistoryHandler.java        |  5 +-
 .../org/apache/solr/handler/sql/SolrSchema.java | 23 +++--
 .../src/java/org/apache/solr/util/SolrCLI.java  | 27 +++---
 .../apache/solr/cloud/HttpPartitionTest.java    |  5 +-
 .../org/apache/solr/cloud/OverseerTest.java     | 17 ++--
 .../TestSolrCloudWithDelegationTokens.java      |  5 +-
 .../hadoop/TestDelegationWithHadoopAuth.java    |  5 +-
 .../solr/client/solrj/impl/CloudSolrClient.java | 53 ++++++++++++
 .../solr/client/solrj/io/SolrClientCache.java   |  8 +-
 .../client/solrj/io/stream/FacetStream.java     |  7 +-
 .../client/solrj/io/stream/RandomStream.java    |  5 +-
 .../solrj/io/stream/TimeSeriesStream.java       |  9 +-
 .../client/solrj/io/stream/TopicStream.java     |  6 +-
 .../client/solrj/io/stream/UpdateStream.java    |  7 +-
 .../solrj/impl/CloudSolrClientBuilderTest.java  | 33 +++----
 .../solrj/impl/CloudSolrClientCacheTest.java    |  4 +-
 .../CloudSolrClientMultiConstructorTest.java    | 44 ++++++++--
 .../client/solrj/impl/CloudSolrClientTest.java  | 15 ++--
 .../java/org/apache/solr/SolrTestCaseJ4.java    | 90 +++++++++++---------
 .../apache/solr/cloud/MiniSolrCloudCluster.java |  3 +-
 25 files changed, 247 insertions(+), 145 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/CHANGES.txt
----------------------------------------------------------------------
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index 03a6ea9..7037532 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -272,6 +272,8 @@ Optimizations
 Other Changes
 ----------------------
 
+* SOLR-11629: Add more intuitive CloudSolrClient.Builder constructors (Varun Thacker, Jason Gerlowski)
+
 * SOLR-11575: Improve ref-guide solrj snippets via mock 'print()' method (Jason Gerlowski via hossman)
 
 * SOLR-11757: In tests, fix race condition on SolrException.ignoreException.

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java
----------------------------------------------------------------------
diff --git a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java
index f65e58f..7a53500 100644
--- a/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java
+++ b/solr/contrib/analytics/src/java/org/apache/solr/analytics/stream/AnalyticsShardRequestManager.java
@@ -21,6 +21,7 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.Callable;
@@ -83,9 +84,7 @@ public class AnalyticsShardRequestManager {
    */
   public void sendRequests(String collection, String zkHost) throws IOException {
     this.replicaUrls = new ArrayList<>();
-    this.cloudSolrClient = new Builder()
-        .withZkHost(zkHost)
-        .build();
+    this.cloudSolrClient = new Builder(Collections.singletonList(zkHost), Optional.empty()).build();
     try {
       this.cloudSolrClient.connect();
       pickShards(collection);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 9d9d2bb..b7b0b62 100644
--- a/solr/core/src/java/org/apache/solr/cloud/ZkController.java
+++ b/solr/core/src/java/org/apache/solr/cloud/ZkController.java
@@ -38,6 +38,7 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ConcurrentHashMap;
@@ -56,7 +57,6 @@ 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.impl.SolrClientCloudManager;
-import org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.WaitForState;
 import org.apache.solr.client.solrj.cloud.autoscaling.TriggerEventType;
 import org.apache.solr.cloud.overseer.OverseerAction;
@@ -614,9 +614,7 @@ public class ZkController {
       if (cloudManager != null) {
         return cloudManager;
       }
-      cloudSolrClient = new CloudSolrClient.Builder()
-          .withClusterStateProvider(new ZkClientClusterStateProvider(zkStateReader))
-          .build();
+      cloudSolrClient = new CloudSolrClient.Builder(Collections.singletonList(zkServerAddress), Optional.empty()).build();
       cloudManager = new SolrClientCloudManager(new ZkDistributedQueueFactory(zkClient), cloudSolrClient);
     }
     return cloudManager;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotsTool.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotsTool.java b/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotsTool.java
index 76e5beb..062f434 100644
--- a/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotsTool.java
+++ b/solr/core/src/java/org/apache/solr/core/snapshots/SolrSnapshotsTool.java
@@ -32,6 +32,7 @@ import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
@@ -90,7 +91,7 @@ public class SolrSnapshotsTool implements Closeable {
   private final CloudSolrClient solrClient;
 
   public SolrSnapshotsTool(String solrZkEnsemble) {
-    solrClient = (new CloudSolrClient.Builder()).withZkHost(solrZkEnsemble).build();
+    solrClient = new CloudSolrClient.Builder(Collections.singletonList(solrZkEnsemble), Optional.empty()).build();
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 d8f3d52..abd6ed7 100644
--- a/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorManager.java
+++ b/solr/core/src/java/org/apache/solr/handler/CdcrReplicatorManager.java
@@ -20,9 +20,11 @@ import java.io.Closeable;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.concurrent.Callable;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
@@ -90,8 +92,7 @@ class CdcrReplicatorManager implements CdcrStateManager.CdcrStateObserver {
         String zkHost = params.get(CdcrParams.ZK_HOST_PARAM);
         String targetCollection = params.get(CdcrParams.TARGET_COLLECTION_PARAM);
 
-        CloudSolrClient client = new Builder()
-            .withZkHost(zkHost)
+        CloudSolrClient client = new Builder(Collections.singletonList(zkHost), Optional.empty())
             .sendUpdatesOnlyToShardLeaders()
             .build();
         client.setDefaultCollection(targetCollection);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/core/src/java/org/apache/solr/handler/admin/AutoscalingHistoryHandler.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/AutoscalingHistoryHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/AutoscalingHistoryHandler.java
index f21bd2c..332d3e5 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/AutoscalingHistoryHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/AutoscalingHistoryHandler.java
@@ -17,9 +17,11 @@
 package org.apache.solr.handler.admin;
 
 import java.lang.invoke.MethodHandles;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -120,8 +122,7 @@ public class AutoscalingHistoryHandler extends RequestHandlerBase implements Per
         }
       }
     }
-    try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder()
-        .withZkHost(coreContainer.getZkController().getZkServerAddress())
+    try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder(Collections.singletonList(coreContainer.getZkController().getZkServerAddress()), Optional.empty())
         .withHttpClient(coreContainer.getUpdateShardHandler().getHttpClient())
         .build()) {
       QueryResponse qr = cloudSolrClient.query(collection, params);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
----------------------------------------------------------------------
diff --git a/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java b/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
index c1bb065..f7318cf 100644
--- a/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
+++ b/solr/core/src/java/org/apache/solr/handler/sql/SolrSchema.java
@@ -16,8 +16,18 @@
  */
 package org.apache.solr.handler.sql;
 
-import com.google.common.collect.ImmutableMap;
-import org.apache.calcite.rel.type.*;
+import java.io.IOException;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Properties;
+
+import org.apache.calcite.rel.type.RelDataType;
+import org.apache.calcite.rel.type.RelDataTypeFactory;
+import org.apache.calcite.rel.type.RelDataTypeImpl;
+import org.apache.calcite.rel.type.RelDataTypeSystem;
+import org.apache.calcite.rel.type.RelProtoDataType;
 import org.apache.calcite.schema.Table;
 import org.apache.calcite.schema.impl.AbstractSchema;
 import org.apache.calcite.sql.type.SqlTypeFactoryImpl;
@@ -30,10 +40,7 @@ import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.luke.FieldFlag;
 
-import java.io.IOException;
-import java.util.EnumSet;
-import java.util.Map;
-import java.util.Properties;
+import com.google.common.collect.ImmutableMap;
 
 class SolrSchema extends AbstractSchema {
   final Properties properties;
@@ -46,7 +53,7 @@ class SolrSchema extends AbstractSchema {
   @Override
   protected Map<String, Table> getTableMap() {
     String zk = this.properties.getProperty("zk");
-    try(CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zk).build()) {
+    try(CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder(Collections.singletonList(zk), Optional.empty()).build()) {
       cloudSolrClient.connect();
       ZkStateReader zkStateReader = cloudSolrClient.getZkStateReader();
       ClusterState clusterState = zkStateReader.getClusterState();
@@ -70,7 +77,7 @@ class SolrSchema extends AbstractSchema {
 
   private Map<String, LukeResponse.FieldInfo> getFieldInfo(String collection) {
     String zk = this.properties.getProperty("zk");
-    try(CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zk).build()) {
+    try(CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder(Collections.singletonList(zk), Optional.empty()).build()) {
       cloudSolrClient.connect();
       LukeRequest lukeRequest = new LukeRequest();
       lukeRequest.setNumTerms(0);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 d8772ee..a768a32 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrCLI.java
+++ b/solr/core/src/java/org/apache/solr/util/SolrCLI.java
@@ -16,12 +16,7 @@
  */
 package org.apache.solr.util;
 
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.solr.common.SolrException.ErrorCode.FORBIDDEN;
-import static org.apache.solr.common.SolrException.ErrorCode.UNAUTHORIZED;
-import static org.apache.solr.common.params.CommonParams.DISTRIB;
-import static org.apache.solr.common.params.CommonParams.NAME;
-
+import javax.net.ssl.SSLPeerUnverifiedException;
 import java.io.Console;
 import java.io.File;
 import java.io.FileNotFoundException;
@@ -45,6 +40,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Base64;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -62,8 +58,6 @@ import java.util.stream.Stream;
 import java.util.zip.ZipEntry;
 import java.util.zip.ZipInputStream;
 
-import javax.net.ssl.SSLPeerUnverifiedException;
-
 import org.apache.commons.cli.CommandLine;
 import org.apache.commons.cli.GnuParser;
 import org.apache.commons.cli.HelpFormatter;
@@ -131,6 +125,12 @@ import org.noggit.ObjectBuilder;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.solr.common.SolrException.ErrorCode.FORBIDDEN;
+import static org.apache.solr.common.SolrException.ErrorCode.UNAUTHORIZED;
+import static org.apache.solr.common.params.CommonParams.DISTRIB;
+import static org.apache.solr.common.params.CommonParams.NAME;
+
 /**
  * Command-line utility for working with Solr.
  */
@@ -206,7 +206,7 @@ public class SolrCLI {
       String zkHost = cli.getOptionValue("zkHost", ZK_HOST);
       
       log.debug("Connecting to Solr cluster: " + zkHost);
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder(Collections.singletonList(zkHost), Optional.empty()).build()) {
 
         String collection = cli.getOptionValue("collection");
         if (collection != null)
@@ -1375,7 +1375,7 @@ public class SolrCLI {
       if (zkHost == null)
         throw new IllegalStateException("Must provide either the '-solrUrl' or '-zkHost' parameters!");
 
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder(Collections.singletonList(zkHost), Optional.empty()).build()) {
         cloudSolrClient.connect();
         Set<String> liveNodes = cloudSolrClient.getZkStateReader().getClusterState().getLiveNodes();
         if (liveNodes.isEmpty())
@@ -1501,7 +1501,7 @@ public class SolrCLI {
             "create_collection can only be used when running in SolrCloud mode.\n");
       }
 
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder(Collections.singletonList(zkHost), Optional.empty()).build()) {
         echoIfVerbose("\nConnecting to ZooKeeper at " + zkHost+" ...", cli);
         cloudSolrClient.connect();
         runCloudTool(cloudSolrClient, cli);
@@ -2380,7 +2380,7 @@ public class SolrCLI {
 
     protected void deleteCollection(CommandLine cli) throws Exception {
       String zkHost = getZkHost(cli);
-      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder().withZkHost(zkHost).build()) {
+      try (CloudSolrClient cloudSolrClient = new CloudSolrClient.Builder(Collections.singletonList(zkHost), Optional.empty()).build()) {
         echoIfVerbose("Connecting to ZooKeeper at " + zkHost, cli);
         cloudSolrClient.connect();
         deleteCollection(cloudSolrClient, cli);
@@ -2984,8 +2984,7 @@ public class SolrCLI {
     protected void waitToSeeLiveNodes(int maxWaitSecs, String zkHost, int numNodes) {
       CloudSolrClient cloudClient = null;
       try {
-        cloudClient = new CloudSolrClient.Builder()
-            .withZkHost(zkHost)
+        cloudClient = new CloudSolrClient.Builder(Collections.singletonList(zkHost), Optional.empty())
             .build();
         cloudClient.connect();
         Set<String> liveNodes = cloudClient.getZkStateReader().getClusterState().getLiveNodes();

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 3d07edc..ce454a7 100644
--- a/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/HttpPartitionTest.java
@@ -22,10 +22,12 @@ import java.lang.invoke.MethodHandles;
 import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -101,8 +103,7 @@ public class HttpPartitionTest extends AbstractFullDistribZkTestBase {
    */
   @Override
   protected CloudSolrClient createCloudClient(String defaultCollection) {
-    CloudSolrClient client = new CloudSolrClient.Builder()
-        .withZkHost(zkServer.getZkAddress())
+    CloudSolrClient client = new CloudSolrClient.Builder(Collections.singletonList(zkServer.getZkAddress()), Optional.empty())
         .sendDirectUpdatesToAnyShardReplica()
         .withConnectionTimeout(30000)
         .withSocketTimeout(60000)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java b/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
index 59cd8f7..77159cf 100644
--- a/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
+++ b/solr/core/src/test/org/apache/solr/cloud/OverseerTest.java
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.when;
 
 import com.codahale.metrics.Snapshot;
 import com.codahale.metrics.Timer;
+
 import java.io.File;
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
@@ -34,6 +35,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
@@ -46,7 +48,6 @@ import org.apache.solr.client.solrj.cloud.DistributedQueue;
 import org.apache.solr.client.solrj.cloud.autoscaling.SolrCloudManager;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.SolrClientCloudManager;
-import org.apache.solr.client.solrj.impl.ZkClientClusterStateProvider;
 import org.apache.solr.cloud.overseer.NodeMutator;
 import org.apache.solr.cloud.overseer.OverseerAction;
 import org.apache.solr.cloud.overseer.ZkWriteCommand;
@@ -687,7 +688,7 @@ public class OverseerTest extends SolrTestCaseJ4 {
       updateShardHandlers.add(updateShardHandler);
       HttpShardHandlerFactory httpShardHandlerFactory = new HttpShardHandlerFactory();
       httpShardHandlerFactorys.add(httpShardHandlerFactory);
-      MockZkController mockZkController = createMockZkController(zkClient, reader);
+      MockZkController mockZkController = createMockZkController(server.getZkAddress(), zkClient, reader);
       Overseer overseer = new Overseer(httpShardHandlerFactory.getShardHandler(), updateShardHandler, "/admin/cores", reader, mockZkController,
           new CloudConfig.CloudConfigBuilder("127.0.0.1", 8983, "").build());
       overseers.add(overseer);
@@ -1313,7 +1314,7 @@ public class OverseerTest extends SolrTestCaseJ4 {
     HttpShardHandlerFactory httpShardHandlerFactory = new HttpShardHandlerFactory();
     httpShardHandlerFactorys.add(httpShardHandlerFactory);
 
-    MockZkController zkController = createMockZkController(zkClient, reader);
+    MockZkController zkController = createMockZkController(address, zkClient, reader);
 
     Overseer overseer = new Overseer(httpShardHandlerFactory.getShardHandler(), updateShardHandler, "/admin/cores", reader, zkController,
         new CloudConfig.CloudConfigBuilder("127.0.0.1", 8983, "").build());
@@ -1325,7 +1326,7 @@ public class OverseerTest extends SolrTestCaseJ4 {
     return zkClient;
   }
 
-  private MockZkController createMockZkController(SolrZkClient zkClient, ZkStateReader reader) {
+  private MockZkController createMockZkController(String zkAddress, SolrZkClient zkClient, ZkStateReader reader) {
     CoreContainer mockAlwaysUpCoreContainer = mock(CoreContainer.class,
         Mockito.withSettings().defaultAnswer(Mockito.CALLS_REAL_METHODS));
     when(mockAlwaysUpCoreContainer.isShutDown()).thenReturn(Boolean.FALSE);  // Allow retry on session expiry
@@ -1335,15 +1336,13 @@ public class OverseerTest extends SolrTestCaseJ4 {
     when(zkController.getCoreContainer()).thenReturn(mockAlwaysUpCoreContainer);
     when(zkController.getZkClient()).thenReturn(zkClient);
     when(zkController.getZkStateReader()).thenReturn(reader);
-    doReturn(getCloudDataProvider(zkClient,reader))
+    doReturn(getCloudDataProvider(zkAddress, zkClient,reader))
         .when(zkController).getSolrCloudManager();
     return zkController;
   }
 
-  private SolrCloudManager getCloudDataProvider(SolrZkClient zkClient, ZkStateReader reader) {
-    CloudSolrClient client = new CloudSolrClient.Builder()
-        .withClusterStateProvider(new ZkClientClusterStateProvider(reader))
-        .build();
+  private SolrCloudManager getCloudDataProvider(String zkAddress, SolrZkClient zkClient, ZkStateReader reader) {
+    CloudSolrClient client = new CloudSolrClient.Builder(Collections.singletonList(zkAddress), Optional.empty()).build();
     solrClients.add(client);
     return new SolrClientCloudManager(new ZkDistributedQueueFactory(zkClient), client);
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
index 8addff2..c9d04d5 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestSolrCloudWithDelegationTokens.java
@@ -43,7 +43,9 @@ import org.junit.BeforeClass;
 import org.junit.Test;
 
 import java.lang.invoke.MethodHandles;
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.Optional;
 import java.util.Set;
 
 import org.slf4j.Logger;
@@ -179,8 +181,7 @@ public class TestSolrCloudWithDelegationTokens extends SolrTestCaseJ4 {
         .withKerberosDelegationToken(token)
         .withResponseParser(client.getParser())
         .build();
-    else delegationTokenClient = new CloudSolrClient.Builder()
-        .withZkHost((miniCluster.getZkServer().getZkAddress()))
+    else delegationTokenClient = new CloudSolrClient.Builder(Collections.singletonList(miniCluster.getZkServer().getZkAddress()), Optional.empty())
         .withLBHttpSolrClientBuilder(new LBHttpSolrClient.Builder()
             .withResponseParser(client.getParser())
             .withHttpSolrClientBuilder(

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/core/src/test/org/apache/solr/security/hadoop/TestDelegationWithHadoopAuth.java
----------------------------------------------------------------------
diff --git a/solr/core/src/test/org/apache/solr/security/hadoop/TestDelegationWithHadoopAuth.java b/solr/core/src/test/org/apache/solr/security/hadoop/TestDelegationWithHadoopAuth.java
index cbe13ba..6411ac4 100644
--- a/solr/core/src/test/org/apache/solr/security/hadoop/TestDelegationWithHadoopAuth.java
+++ b/solr/core/src/test/org/apache/solr/security/hadoop/TestDelegationWithHadoopAuth.java
@@ -16,7 +16,9 @@
  */
 package org.apache.solr.security.hadoop;
 
+import java.util.Collections;
 import java.util.HashSet;
+import java.util.Optional;
 import java.util.Set;
 
 import org.apache.hadoop.security.authentication.client.PseudoAuthenticator;
@@ -167,8 +169,7 @@ public class TestDelegationWithHadoopAuth extends SolrCloudTestCase {
         .withKerberosDelegationToken(token)
         .withResponseParser(client.getParser())
         .build();
-    else delegationTokenClient = new CloudSolrClient.Builder()
-        .withZkHost((cluster.getZkServer().getZkAddress()))
+    else delegationTokenClient = new CloudSolrClient.Builder(Collections.singletonList(cluster.getZkServer().getZkAddress()), Optional.empty())
         .withLBHttpSolrClientBuilder(new LBHttpSolrClient.Builder()
             .withResponseParser(client.getParser())
             .withHttpSolrClientBuilder(

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 dfe15df..17b64ab 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
@@ -30,6 +30,7 @@ import java.util.Iterator;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Random;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
@@ -1356,6 +1357,35 @@ public class CloudSolrClient extends SolrClient {
     protected boolean directUpdatesToLeadersOnly = false;
     protected boolean parallelUpdates = true;
     protected ClusterStateProvider stateProvider;
+    
+    /**
+     * @deprecated use other constructors instead.  This constructor will be changing visibility in an upcoming release.
+     */
+    @Deprecated
+    public Builder() {}
+    
+    /**
+     * Provide a series of Solr URLs to be used when configuring {@link CloudSolrClient} instances.
+     * The solr client will use these urls to understand the cluster topology, which solr nodes are active etc.
+     * 
+     * Provided Solr URLs are expected to point to the root Solr path ("http://hostname:8983/solr"); it should not
+     * include any collections, cores, or other path components.
+     */
+    public Builder(List<String> solrUrls) {
+      this.solrUrls = solrUrls;
+    }
+    
+    /**
+     * Provide a series of ZK hosts which will be used when configuring {@link CloudSolrClient} instances.
+     * 
+     * @param zkHosts a List of at least one ZooKeeper host and port
+     * @param zkChroot the path to the root ZooKeeper node containing Solr data.  May be empty if Solr-data is located
+     * at the ZooKeeper root
+     */
+    public Builder(List<String> zkHosts, Optional<String> zkChroot) {
+      this.zkHosts = zkHosts;
+      if (zkChroot.isPresent()) this.zkChroot = zkChroot.get();
+    }
 
     /**
      * Provide a ZooKeeper client endpoint to be used when configuring {@link CloudSolrClient} instances.
@@ -1365,7 +1395,10 @@ public class CloudSolrClient extends SolrClient {
      * @param zkHost
      *          The client endpoint of the ZooKeeper quorum containing the cloud
      *          state.
+     *          
+     * @deprecated use Zk-host constructor instead
      */
+    @Deprecated
     public Builder withZkHost(String zkHost) {
       this.zkHosts.add(zkHost);
       return this;
@@ -1379,7 +1412,10 @@ public class CloudSolrClient extends SolrClient {
      * 
      * Provided Solr URL is expected to point to the root Solr path ("http://hostname:8983/solr"); it should not
      * include any collections, cores, or other path components.
+     * 
+     * @deprecated use Solr-URL constructor instead
      */
+    @Deprecated
     public Builder withSolrUrl(String solrUrl) {
       this.solrUrls.add(solrUrl);
       return this;
@@ -1392,7 +1428,10 @@ public class CloudSolrClient extends SolrClient {
      * 
      * Provided Solr URLs are expected to point to the root Solr path ("http://hostname:8983/solr"); they should not
      * include any collections, cores, or other path components.
+     * 
+     * @deprecated use Solr URL constructors instead
      */
+    @Deprecated
     public Builder withSolrUrl(Collection<String> solrUrls) {
       this.solrUrls.addAll(solrUrls);
       return this;
@@ -1416,7 +1455,10 @@ public class CloudSolrClient extends SolrClient {
      *          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.
+     *          
+     * @deprecated use Zk-host constructor instead
      */
+    @Deprecated
     public Builder withZkHost(Collection<String> zkHosts) {
       this.zkHosts.addAll(zkHosts);
       return this;
@@ -1424,7 +1466,10 @@ public class CloudSolrClient extends SolrClient {
 
     /**
      * Provides a ZooKeeper chroot for the builder to use when creating clients.
+     * 
+     * @deprecated use Zk-host constructor instead
      */
+    @Deprecated
     public Builder withZkChroot(String zkChroot) {
       this.zkChroot = zkChroot;
       return this;
@@ -1477,6 +1522,14 @@ public class CloudSolrClient extends SolrClient {
       return this;
     }
 
+    /**
+     * Expert feature where you want to implement a custom cluster discovery mechanism of the solr nodes as part of the
+     * cluster.
+     *
+     * @deprecated since this is an expert feature we don't want to expose this to regular users. To use this feature
+     * extend CloudSolrClient.Builder and pass your custom ClusterStateProvider
+     */
+    @Deprecated
     public Builder withClusterStateProvider(ClusterStateProvider stateProvider) {
       this.stateProvider = stateProvider;
       return this;

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 132a1a8..a45c5de 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
@@ -20,7 +20,10 @@ import java.io.IOException;
 import java.io.Serializable;
 import java.lang.invoke.MethodHandles;
 import java.util.Map;
+import java.util.Optional;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 
 import org.apache.http.client.HttpClient;
 import org.apache.solr.client.solrj.SolrClient;
@@ -54,8 +57,9 @@ public class SolrClientCache implements Serializable {
     if (solrClients.containsKey(zkHost)) {
       client = (CloudSolrClient) solrClients.get(zkHost);
     } else {
-      CloudSolrClient.Builder builder = new CloudSolrClient.Builder()
-          .withZkHost(zkHost);
+      final List<String> hosts = new ArrayList<String>();
+      hosts.add(zkHost);
+      CloudSolrClient.Builder builder = new CloudSolrClient.Builder(hosts, Optional.empty());
       if (httpClient != null) {
         builder = builder.withHttpClient(httpClient);
       }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 29e485b..b191085 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
@@ -23,6 +23,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Map.Entry;
 import java.util.stream.Collectors;
 
@@ -323,9 +324,9 @@ public class FacetStream extends TupleStream implements Expressible  {
     if(cache != null) {
       cloudSolrClient = cache.getCloudSolrClient(zkHost);
     } else {
-      cloudSolrClient = new Builder()
-          .withZkHost(zkHost)
-          .build();
+      final List<String> hosts = new ArrayList<>();
+      hosts.add(zkHost);
+      cloudSolrClient = new Builder(hosts, Optional.empty()).build();
     }
 
     FieldComparator[] adjustedSorts = adjustSorts(buckets, bucketSorts);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java
index b26603f..01aa047 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/RandomStream.java
@@ -25,6 +25,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.Random;
 import java.util.stream.Collectors;
 
@@ -175,7 +176,9 @@ public class RandomStream extends TupleStream implements Expressible  {
     if(cache != null) {
       cloudSolrClient = cache.getCloudSolrClient(zkHost);
     } else {
-      cloudSolrClient = (new CloudSolrClient.Builder()).withZkHost(zkHost).build();
+      final List<String> hosts = new ArrayList<>();
+      hosts.add(zkHost);
+      cloudSolrClient = new CloudSolrClient.Builder(hosts, Optional.empty()).build();
     }
 
     ModifiableSolrParams params = getParams(this.props);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java
index 3c2c2b5..610a6df 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/io/stream/TimeSeriesStream.java
@@ -25,6 +25,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Map.Entry;
 import java.util.stream.Collectors;
 
@@ -273,12 +274,12 @@ public class TimeSeriesStream extends TupleStream implements Expressible  {
   }
 
   public void open() throws IOException {
-    if(cache != null) {
+    if (cache != null) {
       cloudSolrClient = cache.getCloudSolrClient(zkHost);
     } else {
-      cloudSolrClient = new Builder()
-          .withZkHost(zkHost)
-          .build();
+      final List<String> hosts = new ArrayList<>();
+      hosts.add(zkHost);
+      cloudSolrClient = new Builder(hosts, Optional.empty()).build();
     }
 
     String json = getJsonFacetString(field, metrics, start, end, gap);

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 4bb6223..9f3cfb6 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
@@ -26,6 +26,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Map.Entry;
 import java.util.Random;
 import java.util.Set;
@@ -294,8 +295,9 @@ public class TopicStream extends CloudSolrStream implements Expressible  {
     if(streamContext.getSolrClientCache() != null) {
       cloudSolrClient = streamContext.getSolrClientCache().getCloudSolrClient(zkHost);
     } else {
-      cloudSolrClient = new Builder()
-          .withZkHost(zkHost)
+      final List<String> hosts = new ArrayList<String>();
+      hosts.add(zkHost);
+      cloudSolrClient = new Builder(hosts, Optional.empty())
           .build();
       this.cloudSolrClient.connect();
     }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 22fbfd8..a08f838 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
@@ -23,6 +23,7 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
+import java.util.Optional;
 
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
@@ -261,9 +262,9 @@ public class UpdateStream extends TupleStream implements Expressible {
     if(this.cache != null) {
       this.cloudSolrClient = this.cache.getCloudSolrClient(zkHost);
     } else {
-      this.cloudSolrClient = new Builder()
-          .withZkHost(zkHost)
-          .build();
+      final List<String> hosts = new ArrayList<>();
+      hosts.add(zkHost);
+      this.cloudSolrClient = new Builder(hosts, Optional.empty()).build();
       this.cloudSolrClient.connect();
     }
   }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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
index 97b79ef..ad6660c 100644
--- 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
@@ -19,6 +19,9 @@ package org.apache.solr.client.solrj.impl;
 
 import java.io.IOException;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Optional;
 
 import org.apache.lucene.util.LuceneTestCase;
 import org.apache.solr.client.solrj.impl.CloudSolrClient.Builder;
@@ -38,9 +41,7 @@ public class CloudSolrClientBuilderTest extends LuceneTestCase {
   
   @Test
   public void testSingleZkHostSpecified() throws IOException {
-    try(CloudSolrClient createdClient = new Builder()
-        .withZkHost(ANY_ZK_HOST)
-        .withZkChroot(ANY_CHROOT)
+    try(CloudSolrClient createdClient = new Builder(Collections.singletonList(ANY_ZK_HOST), Optional.of(ANY_CHROOT))
         .build()) {
       final String clientZkHost = createdClient.getZkHost();
     
@@ -50,10 +51,9 @@ public class CloudSolrClientBuilderTest extends LuceneTestCase {
   
   @Test
   public void testSeveralZkHostsSpecifiedSingly() throws IOException {
-    try (CloudSolrClient createdClient = new Builder()
-        .withZkHost(ANY_ZK_HOST)
-        .withZkHost(ANY_OTHER_ZK_HOST)
-        .withZkChroot(ANY_CHROOT)
+    final List<String> zkHostList = new ArrayList<>();
+    zkHostList.add(ANY_ZK_HOST); zkHostList.add(ANY_OTHER_ZK_HOST);
+    try (CloudSolrClient createdClient = new Builder(zkHostList, Optional.of(ANY_CHROOT))
         .build()) {
       final String clientZkHost = createdClient.getZkHost();
     
@@ -67,10 +67,7 @@ public class CloudSolrClientBuilderTest extends LuceneTestCase {
     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()) {
+    try(CloudSolrClient createdClient = new Builder(zkHosts, Optional.of(ANY_CHROOT)).build()) {
       final String clientZkHost = createdClient.getZkHost();
     
       assertTrue(clientZkHost.contains(ANY_ZK_HOST));
@@ -80,29 +77,21 @@ public class CloudSolrClientBuilderTest extends LuceneTestCase {
   
   @Test
   public void testByDefaultConfiguresClientToSendUpdatesOnlyToShardLeaders() throws IOException {
-    try(CloudSolrClient createdClient = new Builder()
-        .withZkHost(ANY_ZK_HOST)
-        .withZkChroot(ANY_CHROOT)
-        .build()) {
+    try(CloudSolrClient createdClient = new Builder(Collections.singletonList(ANY_ZK_HOST), Optional.of(ANY_CHROOT)).build()) {
       assertTrue(createdClient.isUpdatesToLeaders() == true);
     }
   }
 
   @Test
   public void testIsDirectUpdatesToLeadersOnlyDefault() throws IOException {
-    try(CloudSolrClient createdClient = new Builder()
-        .withZkHost(ANY_ZK_HOST)
-        .withZkChroot(ANY_CHROOT)
-        .build()) {
+    try(CloudSolrClient createdClient = new Builder(Collections.singletonList(ANY_ZK_HOST), Optional.of(ANY_CHROOT)).build()) {
       assertFalse(createdClient.isDirectUpdatesToLeadersOnly());
     }
   }
   
   @Test
   public void test0Timeouts() throws IOException {
-    try(CloudSolrClient createdClient = new Builder()
-        .withZkHost(ANY_ZK_HOST)
-        .withZkChroot(ANY_CHROOT)
+    try(CloudSolrClient createdClient = new Builder(Collections.singletonList(ANY_ZK_HOST), Optional.empty())
         .withSocketTimeout(0)
         .withConnectionTimeout(0)
         .build()) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java
index e666e495..f3920b0 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientCacheTest.java
@@ -80,10 +80,8 @@ public class CloudSolrClientCacheTest extends SolrTestCaseJ4 {
 
     LBHttpSolrClient mockLbclient = getMockLbHttpSolrClient(responses);
     AtomicInteger lbhttpRequestCount = new AtomicInteger();
-    try (CloudSolrClient cloudClient = new CloudSolrClient.Builder()
+    try (CloudSolrClient cloudClient = new CloudSolrClientBuilder(getStateProvider(livenodes, refs))
         .withLBHttpSolrClient(mockLbclient)
-        .withClusterStateProvider(getStateProvider(livenodes, refs))
-
         .build()) {
       livenodes.addAll(ImmutableSet.of("192.168.1.108:7574_solr", "192.168.1.108:8983_solr"));
       ClusterState cs = ClusterState.load(1, coll1State.getBytes(UTF_8),

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientMultiConstructorTest.java
----------------------------------------------------------------------
diff --git a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientMultiConstructorTest.java b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientMultiConstructorTest.java
index e1831f9..dd0328c 100644
--- a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientMultiConstructorTest.java
+++ b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientMultiConstructorTest.java
@@ -16,14 +16,16 @@
  */
 package org.apache.solr.client.solrj.impl;
 
-import org.apache.lucene.util.LuceneTestCase;
-import org.apache.lucene.util.TestUtil;
-import org.junit.Test;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.lucene.util.LuceneTestCase;
+import org.apache.lucene.util.TestUtil;
+import org.junit.Test;
 
 public class CloudSolrClientMultiConstructorTest extends LuceneTestCase {
   
@@ -35,7 +37,7 @@ public class CloudSolrClientMultiConstructorTest extends LuceneTestCase {
   Collection<String> hosts;
 
   @Test
-  public void testWithChroot() throws IOException {
+  public void testZkConnectionStringSetterWithValidChroot() throws IOException {
     boolean setOrList = random().nextBoolean();
     int numOfZKServers = TestUtil.nextInt(random(), 1, 5);
     boolean withChroot = random().nextBoolean();
@@ -70,13 +72,39 @@ public class CloudSolrClientMultiConstructorTest extends LuceneTestCase {
     try (CloudSolrClient client = (new CloudSolrClient.Builder()).withZkHost(hosts).withZkChroot(clientChroot).build()) {
       assertEquals(sb.toString(), client.getZkHost());
     }
+  }
+  
+  @Test
+  public void testZkConnectionStringConstructorWithValidChroot() throws IOException {
+    int numOfZKServers = TestUtil.nextInt(random(), 1, 5);
+    boolean withChroot = random().nextBoolean();
+
+    final String chroot = "/mychroot";
+
+    StringBuilder sb = new StringBuilder();
+
+    List<String> hosts = new ArrayList<>();
+    for (int i=0; i<numOfZKServers; i++) {
+      String ZKString = "host" + i + ":2181";
+      hosts.add(ZKString);
+      sb.append(ZKString);
+      if (i<numOfZKServers -1) sb.append(",");
+    }
 
+    if (withChroot) {
+      sb.append(chroot);
+    }
+
+    final Optional<String> chrootOption = withChroot == false ? Optional.empty() : Optional.of(chroot);
+    try (CloudSolrClient client = new CloudSolrClient.Builder(hosts, chrootOption).build()) {
+      assertEquals(sb.toString(), client.getZkHost());
+    }
   }
   
   @Test(expected = IllegalArgumentException.class)
   public void testBadChroot() {
-    hosts = new ArrayList<>();
-    hosts.add("host1:2181");
-    (new CloudSolrClient.Builder()).withZkHost(hosts).withZkChroot("foo").build();
+    final List<String> zkHosts = new ArrayList<>();
+    zkHosts.add("host1:2181");
+    new CloudSolrClient.Builder(zkHosts, Optional.of("foo")).build();
   }
 }

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 9539846..e54f9ad 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
@@ -22,11 +22,13 @@ import java.net.URL;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.TimeoutException;
 
@@ -104,8 +106,9 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
     AbstractDistribZkTestBase.waitForRecoveriesToFinish(COLLECTION, cluster.getSolrClient().getZkStateReader(),
         false, true, TIMEOUT);
     
-    httpBasedCloudSolrClient = new CloudSolrClient.Builder().withSolrUrl(
-        cluster.getJettySolrRunner(0).getBaseUrl().toString()).build();
+    final List<String> solrUrls = new ArrayList<>();
+    solrUrls.add(cluster.getJettySolrRunner(0).getBaseUrl().toString());
+    httpBasedCloudSolrClient = new CloudSolrClient.Builder(solrUrls).build();
   }
 
   @AfterClass
@@ -269,8 +272,8 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
     assertEquals(0, docs.getNumFound());
     
     // Test Multi-Threaded routed updates for UpdateRequest
-    try (CloudSolrClient threadedClient = new CloudSolrClientBuilder()
-        .withZkHost(cluster.getZkServer().getZkAddress())
+    try (CloudSolrClient threadedClient = new CloudSolrClientBuilder
+        (Collections.singletonList(cluster.getZkServer().getZkAddress()), Optional.empty())
         .withParallelUpdates(true)
         .build()) {
       threadedClient.setDefaultCollection(COLLECTION);
@@ -789,8 +792,8 @@ public class CloudSolrClientTest extends SolrCloudTestCase {
     final String old_leader_core_node_name = slice.getLeader().getName();
 
     // NOTE: creating our own CloudSolrClient whose settings we can muck with...
-    try (CloudSolrClient stale_client = new CloudSolrClientBuilder()
-        .withZkHost(cluster.getZkServer().getZkAddress())
+    try (CloudSolrClient stale_client = new CloudSolrClientBuilder
+        (Collections.singletonList(cluster.getZkServer().getZkAddress()), Optional.empty())
         .sendDirectUpdatesToAnyShardReplica()
         .withParallelUpdates(true)
         .build()) {

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 bef9519..e090246 100644
--- a/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
+++ b/solr/test-framework/src/java/org/apache/solr/SolrTestCaseJ4.java
@@ -55,6 +55,7 @@ import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
 import java.util.concurrent.CopyOnWriteArraySet;
@@ -66,6 +67,7 @@ import com.carrotsearch.randomizedtesting.TraceFormatting;
 import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters;
 import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering;
 import com.carrotsearch.randomizedtesting.rules.SystemPropertiesRestoreRule;
+
 import org.apache.commons.io.FileUtils;
 import org.apache.http.client.HttpClient;
 import org.apache.lucene.analysis.MockAnalyzer;
@@ -79,7 +81,9 @@ import org.apache.lucene.util.QuickPatchThreadsFilter;
 import org.apache.lucene.util.TestUtil;
 import org.apache.solr.client.solrj.ResponseParser;
 import org.apache.solr.client.solrj.embedded.JettyConfig;
+import org.apache.solr.client.solrj.embedded.JettySolrRunner;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
+import org.apache.solr.client.solrj.impl.ClusterStateProvider;
 import org.apache.solr.client.solrj.impl.ConcurrentUpdateSolrClient;
 import org.apache.solr.client.solrj.impl.HttpClientUtil;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
@@ -2234,22 +2238,43 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    * some internal settings.
    */
   public static class CloudSolrClientBuilder extends CloudSolrClient.Builder {
-
-    public CloudSolrClientBuilder() {
-      this.directUpdatesToLeadersOnly = random().nextBoolean();
-      this.shardLeadersOnly = random().nextBoolean();
-      this.parallelUpdates = random().nextBoolean();
+    
+    public CloudSolrClientBuilder(List<String> zkHosts, Optional<String> zkChroot) {
+      super(zkHosts, zkChroot);
+      randomizeCloudSolrClient();
     }
-
-    /** Randomly chooses the cluster state provider -- either ZK based or HTTP. */
-    public CloudSolrClient.Builder withCluster(MiniSolrCloudCluster cluster) {
+    
+    public CloudSolrClientBuilder(ClusterStateProvider stateProvider) {
+      this.stateProvider = stateProvider;
+      randomizeCloudSolrClient();
+    }
+    
+    public CloudSolrClientBuilder(MiniSolrCloudCluster cluster) {
       if (random().nextBoolean()) {
-        return withZkHost(cluster.getZkServer().getZkAddress());
+        this.zkHosts.add(cluster.getZkServer().getZkAddress());
       } else {
-        return withSolrUrl(cluster.getRandomJetty(random()).getBaseUrl().toString());
+        populateSolrUrls(cluster);
       }
+      
+      randomizeCloudSolrClient();
+    }
+    
+    private void populateSolrUrls(MiniSolrCloudCluster cluster) {
+      if (random().nextBoolean()) {
+        final List<JettySolrRunner> solrNodes = cluster.getJettySolrRunners();
+        for (JettySolrRunner node : solrNodes) {
+          this.solrUrls.add(node.getBaseUrl().toString());
+        }
+      } else {
+        this.solrUrls.add(cluster.getRandomJetty(random()).getBaseUrl().toString());
+      }
+    }
+    
+    private void randomizeCloudSolrClient() {
+      this.directUpdatesToLeadersOnly = random().nextBoolean();
+      this.shardLeadersOnly = random().nextBoolean();
+      this.parallelUpdates = random().nextBoolean();
     }
-
   }
 
   /**
@@ -2258,9 +2283,7 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    * {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
    */ 
   public static CloudSolrClient getCloudSolrClient(String zkHost) {
-    return new CloudSolrClientBuilder()
-        .withZkHost(zkHost)
-        .build();
+    return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty()).build();
   }
 
   /**
@@ -2269,9 +2292,7 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    * {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
    */
   public static CloudSolrClient getCloudSolrClient(MiniSolrCloudCluster cluster) {
-    return new CloudSolrClientBuilder()
-        .withCluster(cluster)
-        .build();
+    return new CloudSolrClientBuilder(cluster).build();
   }
 
   /**
@@ -2280,8 +2301,7 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    * {@link org.apache.solr.client.solrj.impl.CloudSolrClient.Builder} class directly
    */ 
   public static CloudSolrClient getCloudSolrClient(String zkHost, HttpClient httpClient) {
-    return new CloudSolrClientBuilder()
-        .withZkHost(zkHost)
+    return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
         .withHttpClient(httpClient)
         .build();
   }
@@ -2293,19 +2313,17 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    */ 
   public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly) {
     if (shardLeadersOnly) {
-      return new CloudSolrClientBuilder()
-          .withZkHost(zkHost)
+      return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
           .sendUpdatesOnlyToShardLeaders()
           .build();
     }
-    return new CloudSolrClientBuilder()
-        .withZkHost(zkHost)
+    return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
         .sendUpdatesToAllReplicasInShard()
         .build();
   }
 
   public static CloudSolrClientBuilder newCloudSolrClient(String zkHost) {
-    return (CloudSolrClientBuilder) new CloudSolrClientBuilder().withZkHost(zkHost);
+    return (CloudSolrClientBuilder) new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty());
   }
 
   /**
@@ -2315,14 +2333,12 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    */ 
   public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, int socketTimeoutMillis) {
     if (shardLeadersOnly) {
-      return new CloudSolrClientBuilder()
-          .withZkHost(zkHost)
+      return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
           .sendUpdatesOnlyToShardLeaders()
           .withSocketTimeout(socketTimeoutMillis)
           .build();
     }
-    return new CloudSolrClientBuilder()
-        .withZkHost(zkHost)
+    return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
         .sendUpdatesToAllReplicasInShard()
         .withSocketTimeout(socketTimeoutMillis)
         .build();
@@ -2335,15 +2351,13 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    */ 
   public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, int connectionTimeoutMillis, int socketTimeoutMillis) {
     if (shardLeadersOnly) {
-      return new CloudSolrClientBuilder()
-          .withZkHost(zkHost)
+      return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
           .sendUpdatesOnlyToShardLeaders()
           .withConnectionTimeout(connectionTimeoutMillis)
           .withSocketTimeout(socketTimeoutMillis)
           .build();
     }
-    return new CloudSolrClientBuilder()
-        .withZkHost(zkHost)
+    return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
         .sendUpdatesToAllReplicasInShard()
         .withConnectionTimeout(connectionTimeoutMillis)
         .withSocketTimeout(socketTimeoutMillis)
@@ -2359,14 +2373,12 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
    */ 
   public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, HttpClient httpClient) {
     if (shardLeadersOnly) {
-      return new CloudSolrClientBuilder()
-          .withZkHost(zkHost)
+      return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
           .withHttpClient(httpClient)
           .sendUpdatesOnlyToShardLeaders()
           .build();
     }
-    return new CloudSolrClientBuilder()
-        .withZkHost(zkHost)
+    return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
         .withHttpClient(httpClient)
         .sendUpdatesToAllReplicasInShard()
         .build();
@@ -2380,16 +2392,14 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
   public static CloudSolrClient getCloudSolrClient(String zkHost, boolean shardLeadersOnly, HttpClient httpClient,
       int connectionTimeoutMillis, int socketTimeoutMillis) {
     if (shardLeadersOnly) {
-      return new CloudSolrClientBuilder()
-          .withZkHost(zkHost)
+      return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
           .withHttpClient(httpClient)
           .sendUpdatesOnlyToShardLeaders()
           .withConnectionTimeout(connectionTimeoutMillis)
           .withSocketTimeout(socketTimeoutMillis)
           .build();
     }
-    return new CloudSolrClientBuilder()
-        .withZkHost(zkHost)
+    return new CloudSolrClientBuilder(Collections.singletonList(zkHost), Optional.empty())
         .withHttpClient(httpClient)
         .sendUpdatesToAllReplicasInShard()
         .withConnectionTimeout(connectionTimeoutMillis)

http://git-wip-us.apache.org/repos/asf/lucene-solr/blob/1d55336d/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 9ffea0f..2f9ef12 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
@@ -498,8 +498,7 @@ public class MiniSolrCloudCluster {
   }
   
   protected CloudSolrClient buildSolrClient() {
-    return new Builder()
-        .withZkHost(getZkServer().getZkAddress())
+    return new Builder(Collections.singletonList(getZkServer().getZkAddress()), Optional.empty())
         .build();
   }