This is an automated email from the ASF dual-hosted git repository.

gerlowskija pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/solr.git


The following commit(s) were added to refs/heads/main by this push:
     new e08d7f0f0e6 SOLR-17043: Remove SolrClient path pattern matching (#3238)
e08d7f0f0e6 is described below

commit e08d7f0f0e66cdde389eb843db341f0eb5d833bb
Author: Jude Muriithi <[email protected]>
AuthorDate: Thu Apr 17 12:01:42 2025 -0400

    SOLR-17043: Remove SolrClient path pattern matching (#3238)
    
    Prior to this commit, the LB and Cloud clients looked at the URL path to 
make
    some decisions around request routing, etc.  This logic was brittle and not
    really scalable to the more varied paths in Solr's v2 APIs.  This commit
    replaces that logic to instead use a "request type" enum already that
    SolrRequest objects make available.
    
    ---------
    
    Co-authored-by: jmuriithi3 <[email protected]>
    Co-authored-by: Jason Gerlowski <[email protected]>
---
 solr/CHANGES.txt                                   |   2 +
 .../solr/cloud/api/collections/SplitShardCmd.java  |   3 +-
 .../org/apache/solr/handler/SolrConfigHandler.java |   8 +-
 .../org/apache/solr/schema/ManagedIndexSchema.java |   8 +-
 .../TestEmbeddedSolrServerAdminHandler.java        |   7 +-
 .../org/apache/solr/cloud/TestConfigSetsAPI.java   |   8 +-
 .../apache/solr/cloud/TestRebalanceLeaders.java    |  29 +++--
 .../api/collections/ReplicaPropertiesBase.java     |   8 +-
 .../cloud/api/collections/TestCollectionAPI.java   | 124 +++++++++++----------
 .../api/collections/TestReplicaProperties.java     |   8 +-
 .../solr/handler/RequestHandlerMetricsTest.java    |   4 +-
 .../solr/handler/admin/AdminHandlersProxyTest.java |  21 +++-
 .../solr/handler/admin/HealthCheckHandlerTest.java |   3 +-
 .../response/TestPrometheusResponseWriter.java     |  10 +-
 .../solr/security/BasicAuthIntegrationTest.java    |   3 +-
 .../solr/opentelemetry/TestDistributedTracing.java |   4 +-
 .../solr/prometheus/scraper/SolrScraper.java       |  33 ++++--
 .../org/apache/solr/client/solrj/SolrRequest.java  |  21 +++-
 .../solr/client/solrj/impl/CloudSolrClient.java    |  70 ++++++------
 .../solr/client/solrj/impl/HttpSolrClient.java     |   2 +-
 .../solr/client/solrj/impl/LBHttp2SolrClient.java  |   9 +-
 .../solr/client/solrj/impl/LBSolrClient.java       |   9 +-
 .../solrj/request/AbstractUpdateRequest.java       |  22 +---
 .../solrj/request/CollectionAdminRequest.java      |   6 +-
 .../request/CollectionRequiringSolrRequest.java    |   4 +-
 .../solrj/request/ConfigSetAdminRequest.java       |   9 +-
 .../client/solrj/request/CoreAdminRequest.java     |   9 +-
 .../solrj/request/DelegationTokenRequest.java      |  17 +--
 .../client/solrj/request/DirectXmlRequest.java     |   7 +-
 .../solrj/request/DocumentAnalysisRequest.java     |   9 +-
 .../client/solrj/request/FieldAnalysisRequest.java |   9 +-
 .../client/solrj/request/GenericSolrRequest.java   |  31 +++++-
 .../client/solrj/request/GenericV2SolrRequest.java |  25 +++++
 .../client/solrj/request/HealthCheckRequest.java   |   7 +-
 .../solr/client/solrj/request/IsUpdateRequest.java |   8 +-
 .../solr/client/solrj/request/LukeRequest.java     |  10 +-
 .../solr/client/solrj/request/QueryRequest.java    |  11 +-
 .../apache/solr/client/solrj/request/SolrPing.java |   7 +-
 .../solr/client/solrj/request/UpdateRequest.java   |  10 ++
 .../solr/client/solrj/request/V2Request.java       |  12 +-
 .../request/schema/AbstractSchemaRequest.java      |   7 +-
 .../apache/solr/common/params/CommonParams.java    |   2 +
 .../solrj/src/resources/java-template/api.mustache |  10 +-
 .../apache/solr/client/solrj/SolrExampleTests.java |   1 +
 .../solrj/impl/CloudHttp2SolrClientRetryTest.java  |  17 +--
 .../solrj/impl/CloudHttp2SolrClientTest.java       |  11 +-
 .../solrj/impl/CloudSolrClientRetryTest.java       |  16 +--
 .../client/solrj/impl/CloudSolrClientTest.java     |  10 +-
 .../impl/SendUpdatesToLeadersOverrideTest.java     |   7 +-
 .../cloud/AbstractBasicDistributedZkTestBase.java  |   6 +-
 .../solr/cloud/AbstractFullDistribZkTestBase.java  |  11 +-
 .../java/org/apache/solr/cloud/ConfigRequest.java  |   7 +-
 ...bstractCollectionsAPIDistributedZkTestBase.java |  25 +++--
 53 files changed, 388 insertions(+), 349 deletions(-)

diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index a471e3c872e..5a8522e5ba9 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -45,6 +45,8 @@ Improvements
   Simplified the V2 API to remove the needless SolrResponse.  And moved 
JSON/Jackson binding into
   a new JacksonDataBindResponseParser (David Smiley)
 
+* SOLR-17043: "LB" and "Cloud" clients no longer use brittle URL 
pattern-matching when routing requests. (Jude Muriithi via David Smiley, Jason 
Gerlowski)
+
 Optimizations
 ---------------------
 * SOLR-17568: The CLI bin/solr export tool now contacts the appropriate nodes 
directly for data instead of proxying through one.
diff --git 
a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java 
b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
index 60f25c324b2..662221cca7f 100644
--- 
a/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
+++ 
b/solr/core/src/java/org/apache/solr/cloud/api/collections/SplitShardCmd.java
@@ -858,7 +858,8 @@ public class SplitShardCmd implements 
CollApiCmds.CollectionApiCommand {
             .add("key", indexSizeMetricName)
             .add("key", freeDiskSpaceMetricName);
     SolrResponse rsp =
-        new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/metrics", 
params)
+        new GenericSolrRequest(
+                SolrRequest.METHOD.GET, "/admin/metrics", 
SolrRequest.SolrRequestType.ADMIN, params)
             .process(cloudManager.getSolrClient());
 
     Number size = (Number) rsp.getResponse().findRecursive("metrics", 
indexSizeMetricName);
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 87c2eec2a72..32093a5031f 100644
--- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
@@ -54,7 +54,6 @@ import java.util.concurrent.locks.ReentrantLock;
 import org.apache.solr.api.AnnotatedApi;
 import org.apache.solr.api.Api;
 import org.apache.solr.api.ApiBag;
-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.io.stream.expr.Expressible;
@@ -966,7 +965,7 @@ public class SolrConfigHandler extends RequestHandlerBase
     int maxWait;
 
     PerReplicaCallable(Replica replica, String prop, int expectedZkVersion, 
int maxWait) {
-      super(METHOD.GET, "/config/" + ZNODEVER);
+      super(METHOD.GET, "/config/" + ZNODEVER, SolrRequestType.ADMIN);
       this.replica = replica;
       this.expectedZkVersion = expectedZkVersion;
       this.prop = prop;
@@ -1030,11 +1029,6 @@ public class SolrConfigHandler extends RequestHandlerBase
     protected SolrResponse createResponse(NamedList<Object> namedList) {
       return null;
     }
-
-    @Override
-    public String getRequestType() {
-      return SolrRequest.SolrRequestType.ADMIN.toString();
-    }
   }
 
   @Override
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 d8ede1027ed..a6eed580e75 100644
--- a/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
+++ b/solr/core/src/java/org/apache/solr/schema/ManagedIndexSchema.java
@@ -40,7 +40,6 @@ import java.util.concurrent.Future;
 import java.util.concurrent.TimeUnit;
 import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.util.Version;
-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.request.CollectionRequiringSolrRequest;
@@ -356,7 +355,7 @@ public final class ManagedIndexSchema extends IndexSchema {
 
     GetZkSchemaVersionCallable(
         String baseUrl, String coreName, int expectedZkVersion, ZkController 
zkController) {
-      super(METHOD.GET, "/schema/zkversion");
+      super(METHOD.GET, "/schema/zkversion", SolrRequestType.ADMIN);
       this.zkController = zkController;
       this.baseUrl = baseUrl;
       this.coreName = coreName;
@@ -412,11 +411,6 @@ public final class ManagedIndexSchema extends IndexSchema {
     protected SolrResponse createResponse(NamedList<Object> namedList) {
       return null;
     }
-
-    @Override
-    public String getRequestType() {
-      return SolrRequest.SolrRequestType.ADMIN.toString();
-    }
   }
 
   public static class FieldExistsException extends SolrException {
diff --git 
a/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestEmbeddedSolrServerAdminHandler.java
 
b/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestEmbeddedSolrServerAdminHandler.java
index 450db6cc514..7118520fa12 100644
--- 
a/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestEmbeddedSolrServerAdminHandler.java
+++ 
b/solr/core/src/test/org/apache/solr/client/solrj/embedded/TestEmbeddedSolrServerAdminHandler.java
@@ -47,7 +47,7 @@ public class TestEmbeddedSolrServerAdminHandler extends 
SolrTestCaseJ4 {
   private static class SystemInfoRequest extends SolrRequest<QueryResponse> {
 
     public SystemInfoRequest() {
-      super(METHOD.GET, "/admin/info/system");
+      super(METHOD.GET, "/admin/info/system", 
SolrRequest.SolrRequestType.ADMIN);
     }
 
     @Override
@@ -59,10 +59,5 @@ public class TestEmbeddedSolrServerAdminHandler extends 
SolrTestCaseJ4 {
     protected QueryResponse createResponse(final NamedList<Object> namedList) {
       return new QueryResponse();
     }
-
-    @Override
-    public String getRequestType() {
-      return SolrRequest.SolrRequestType.ADMIN.toString();
-    }
   }
 }
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 64c858ac4ea..1ed5c1568bb 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestConfigSetsAPI.java
@@ -67,6 +67,8 @@ import org.apache.http.util.EntityUtils;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.api.AnnotatedApi;
 import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudLegacySolrClient;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
@@ -74,7 +76,7 @@ import 
org.apache.solr.client.solrj.request.ConfigSetAdminRequest;
 import org.apache.solr.client.solrj.request.ConfigSetAdminRequest.Create;
 import org.apache.solr.client.solrj.request.ConfigSetAdminRequest.Delete;
 import org.apache.solr.client.solrj.request.ConfigSetAdminRequest.Upload;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.request.schema.SchemaRequest;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
 import org.apache.solr.client.solrj.response.ConfigSetAdminResponse;
@@ -1487,8 +1489,8 @@ public class TestConfigSetsAPI extends SolrCloudTestCase {
     params.set("name", collectionName);
     params.set("numShards", numShards);
     params.set("replicationFactor", replicationFactor);
-    QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
     CollectionAdminResponse res = new CollectionAdminResponse();
     res.setResponse(client.request(request));
diff --git a/solr/core/src/test/org/apache/solr/cloud/TestRebalanceLeaders.java 
b/solr/core/src/test/org/apache/solr/cloud/TestRebalanceLeaders.java
index b7a15aea1b6..762802ddd45 100644
--- a/solr/core/src/test/org/apache/solr/cloud/TestRebalanceLeaders.java
+++ b/solr/core/src/test/org/apache/solr/cloud/TestRebalanceLeaders.java
@@ -29,17 +29,20 @@ import java.util.TreeMap;
 import java.util.TreeSet;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.TimeUnit;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
-import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.client.solrj.response.SimpleSolrResponse;
 import org.apache.solr.common.cloud.DocCollection;
 import org.apache.solr.common.cloud.Replica;
 import org.apache.solr.common.cloud.Slice;
 import org.apache.solr.common.params.CollectionParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.ExecutorUtil;
+import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.TimeSource;
 import org.apache.solr.embedded.JettySolrRunner;
 import org.apache.solr.util.TimeOut;
@@ -408,13 +411,14 @@ public class TestRebalanceLeaders extends 
SolrCloudTestCase {
     ModifiableSolrParams params = new ModifiableSolrParams();
     params.set("action", 
CollectionParams.CollectionAction.REBALANCELEADERS.toString());
     params.set("collection", COLLECTION_NAME);
-    QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
-    QueryResponse resp = request.process(cluster.getSolrClient());
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
+    SimpleSolrResponse resp = request.process(cluster.getSolrClient());
     assertTrue(
         "All leaders should have been verified",
         resp.getResponse().get("Summary").toString().contains("Success"));
-    assertEquals("Call to rebalanceLeaders failed ", 0, resp.getStatus());
+    NamedList<?> header = (NamedList) resp.getResponse().get("responseHeader");
+    assertEquals("Call to rebalanceLeaders failed ", 0, header.get("status"));
   }
 
   private void rebalancePropUsingSolrJAPI(String prop) throws IOException, 
SolrServerException {
@@ -445,10 +449,11 @@ public class TestRebalanceLeaders extends 
SolrCloudTestCase {
     if (prop.toLowerCase(Locale.ROOT).contains("preferredleader") == false) {
       params.set("shardUnique", true);
     }
-    QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
-    QueryResponse resp = request.process(cluster.getSolrClient());
-    assertEquals("Call to rebalanceLeaders failed ", 0, resp.getStatus());
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
+    var resp = request.process(cluster.getSolrClient());
+    NamedList<?> header = (NamedList) resp.getResponse().get("responseHeader");
+    assertEquals("Call to rebalanceLeaders failed ", 0, header.get("status"));
   }
 
   // This important. I've (Erick Erickson) run across a situation where the 
"standard request"
@@ -479,8 +484,8 @@ public class TestRebalanceLeaders extends SolrCloudTestCase 
{
       params.set("shardUnique", "true");
     }
 
-    QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
     cluster.getSolrClient().request(request);
     String propLC = prop.toLowerCase(Locale.ROOT);
     waitForState(
diff --git 
a/solr/core/src/test/org/apache/solr/cloud/api/collections/ReplicaPropertiesBase.java
 
b/solr/core/src/test/org/apache/solr/cloud/api/collections/ReplicaPropertiesBase.java
index 6e81a24c1ec..8d9949ce1b3 100644
--- 
a/solr/core/src/test/org/apache/solr/cloud/api/collections/ReplicaPropertiesBase.java
+++ 
b/solr/core/src/test/org/apache/solr/cloud/api/collections/ReplicaPropertiesBase.java
@@ -22,9 +22,11 @@ import java.util.HashSet;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.cloud.AbstractFullDistribZkTestBase;
 import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.DocCollection;
@@ -47,8 +49,8 @@ public abstract class ReplicaPropertiesBase extends 
AbstractFullDistribZkTestBas
     for (int idx = 0; idx < paramsIn.length; idx += 2) {
       params.set(paramsIn[idx], paramsIn[idx + 1]);
     }
-    QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
     return client.request(request);
   }
 
diff --git 
a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestCollectionAPI.java
 
b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestCollectionAPI.java
index ce605c70271..26d6528881f 100644
--- 
a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestCollectionAPI.java
+++ 
b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestCollectionAPI.java
@@ -27,11 +27,13 @@ import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.LongAdder;
 import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.NoOpResponseParser;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
 import org.apache.solr.cloud.MiniSolrCloudCluster;
 import org.apache.solr.cloud.ZkConfigSetService;
@@ -120,8 +122,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.MODIFYCOLLECTION.toString());
       params.set("collection", COLLECTION_NAME);
       params.set("replicationFactor", 25);
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       client.request(request);
       NamedList<Object> rsp =
@@ -141,9 +143,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.MODIFYCOLLECTION.toString());
       params.set("collection", COLLECTION_NAME);
       params.set("replicationFactor", "");
-      request = new QueryRequest(params);
-      request.setPath("/admin/collections");
-
+      request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       client.request(request);
 
       rsp =
@@ -164,8 +165,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.MODIFYCOLLECTION.toString());
       params.set("collection", COLLECTION_NAME);
       params.set("non_existent_property", "");
-      request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       try {
         client.request(request);
@@ -186,8 +187,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("numShards", "1");
       params.set("replicationFactor", "1");
       params.set("nrtReplicas", "2");
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       try {
         client.request(request);
@@ -214,8 +215,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.MODIFYCOLLECTION.toString());
       params.set("collection", "test_repFactorColl");
       params.set("replicationFactor", "4");
-      request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       client.request(request);
 
       assertCountsForRepFactorAndNrtReplicas(client, "test_repFactorColl");
@@ -240,9 +241,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("numShards", "1");
       params.set("replicationFactor", "1");
       params.set("collection.configName", configSet);
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
-
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       client.request(request);
 
       waitForCollection(ZkStateReader.from(client), collection, 1);
@@ -278,8 +278,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
     ModifiableSolrParams params = new ModifiableSolrParams();
     params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
     params.set("collection", collectionName);
-    QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
     NamedList<Object> rsp = client.request(request);
     NamedList<?> cluster = (NamedList<?>) rsp.get("cluster");
@@ -300,8 +300,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", COLLECTION_NAME);
       params.set("shard", SHARD1);
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
       NamedList<?> cluster = (NamedList<?>) rsp.get("cluster");
@@ -441,8 +441,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
     try (CloudSolrClient client = createCloudClient(null)) {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("action", CollectionParams.CollectionAction.LIST.toString());
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
       List<?> collections = (List<?>) rsp.get("collections");
@@ -461,8 +461,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
     try (CloudSolrClient client = createCloudClient(null)) {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
       NamedList<?> cluster = (NamedList<?>) rsp.get("cluster");
@@ -483,8 +483,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", COLLECTION_NAME);
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
       NamedList<?> cluster = (NamedList<?>) rsp.get("cluster");
@@ -513,8 +513,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", cname);
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
       NamedList<Object> cluster = (NamedList<Object>) rsp.get("cluster");
@@ -554,8 +554,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", DEFAULT_COLLECTION);
       params.set(ShardParams._ROUTE_, "a!");
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
       @SuppressWarnings({"unchecked"})
@@ -586,8 +586,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.CREATEALIAS.toString());
       params.set("name", "myalias");
       params.set("collections", DEFAULT_COLLECTION + "," + COLLECTION_NAME);
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       client.request(request);
 
@@ -595,8 +595,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", DEFAULT_COLLECTION);
-      request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
 
@@ -621,8 +621,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", "myalias");
-      request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       // SOLR-12938 - this should NOT cause an exception
       rsp = client.request(request);
@@ -638,7 +638,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", "notAnAliasOrCollection");
-      request = new QueryRequest(params);
+      request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       request.setPath("/admin/collections");
 
       // SOLR-12938 - this should still cause an exception
@@ -663,9 +664,9 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("collection", COLLECTION_NAME);
       params.set("shard", SHARD1);
       params.set("wt", "json");
-      QueryRequest request = new QueryRequest(params);
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       request.setResponseParser(new NoOpResponseParser("json"));
-      request.setPath("/admin/collections");
       NamedList<Object> rsp = client.request(request);
       String actualResponse = (String) rsp.get("response");
 
@@ -694,15 +695,15 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.ADDROLE.toString());
       params.set("node", replica.getNodeName());
       params.set("role", "overseer");
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       client.request(request);
 
       params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", DEFAULT_COLLECTION);
-      request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
       NamedList<?> cluster = (NamedList<?>) rsp.get("cluster");
@@ -722,8 +723,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CLUSTERSTATUS.toString());
       params.set("collection", "bad_collection_name");
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       try {
         client.request(request);
@@ -772,8 +773,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       missingParamsError(client, params);
       params.set("property.value", "true");
 
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       client.request(request);
 
       // The above should have set exactly one preferredleader...
@@ -1143,8 +1144,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.CREATE.toString());
       params.set("name", "invalid@name#with$weird%characters");
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       try {
         client.request(request);
@@ -1166,8 +1167,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("router.name", "implicit");
       params.set("numShards", "1");
       params.set("shards", "invalid@name#with$weird%characters");
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       try {
         client.request(request);
@@ -1187,8 +1188,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("action", 
CollectionParams.CollectionAction.CREATEALIAS.toString());
       params.set("name", "invalid@name#with$weird%characters");
       params.set("collections", COLLECTION_NAME);
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       try {
         client.request(request);
@@ -1211,8 +1212,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("name", "valid_collection_name");
       params.set("shards", "a");
       params.set("router.name", "implicit");
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       client.request(request);
 
       params = new ModifiableSolrParams();
@@ -1220,8 +1221,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("collection", "valid_collection_name");
       params.set("shard", "invalid@name#with$weird%characters");
 
-      request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       try {
         client.request(request);
@@ -1257,10 +1258,11 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
   private void missingParamsError(CloudSolrClient client, ModifiableSolrParams 
origParams)
       throws IOException, SolrServerException {
 
-    QueryRequest request;
+    GenericSolrRequest request;
     try {
-      request = new QueryRequest(origParams);
-      request.setPath("/admin/collections");
+      request =
+          new GenericSolrRequest(
+              METHOD.GET, "/admin/collections", SolrRequestType.ADMIN, 
origParams);
       client.request(request);
       fail("Should have thrown a SolrException due to lack of a required 
parameter.");
     } catch (SolrException se) {
@@ -1349,8 +1351,8 @@ public class TestCollectionAPI extends 
ReplicaPropertiesBase {
       params.set("collection.configName", "conf1");
       params.set("numShards", "1");
       params.set(CollectionAdminParams.PER_REPLICA_STATE, "False");
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       try {
         client.request(request);
diff --git 
a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestReplicaProperties.java
 
b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestReplicaProperties.java
index 11a5dde4612..ca2d3f3c8d7 100644
--- 
a/solr/core/src/test/org/apache/solr/cloud/api/collections/TestReplicaProperties.java
+++ 
b/solr/core/src/test/org/apache/solr/cloud/api/collections/TestReplicaProperties.java
@@ -20,9 +20,11 @@ import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.ClusterState;
 import org.apache.solr.common.cloud.Replica;
@@ -67,8 +69,8 @@ public class TestReplicaProperties extends 
ReplicaPropertiesBase {
     try (CloudSolrClient client = createCloudClient(null)) {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("action", CollectionParams.CollectionAction.LIST.toString());
-      QueryRequest request = new QueryRequest(params);
-      request.setPath("/admin/collections");
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
       NamedList<Object> rsp = client.request(request);
       @SuppressWarnings({"unchecked"})
diff --git 
a/solr/core/src/test/org/apache/solr/handler/RequestHandlerMetricsTest.java 
b/solr/core/src/test/org/apache/solr/handler/RequestHandlerMetricsTest.java
index b5b73de2597..96a038f7bc4 100644
--- a/solr/core/src/test/org/apache/solr/handler/RequestHandlerMetricsTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/RequestHandlerMetricsTest.java
@@ -81,7 +81,9 @@ public class RequestHandlerMetricsTest extends 
SolrCloudTestCase {
     cloudClient.query(collection2, solrQuery);
 
     NamedList<Object> response =
-        cloudClient.request(new GenericSolrRequest(SolrRequest.METHOD.GET, 
"/admin/metrics"));
+        cloudClient.request(
+            new GenericSolrRequest(
+                SolrRequest.METHOD.GET, "/admin/metrics", 
SolrRequest.SolrRequestType.ADMIN));
 
     NamedList<Object> metrics = (NamedList<Object>) response.get("metrics");
 
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/AdminHandlersProxyTest.java 
b/solr/core/src/test/org/apache/solr/handler/admin/AdminHandlersProxyTest.java
index b6f74ddfba6..cdc9ca26494 100644
--- 
a/solr/core/src/test/org/apache/solr/handler/admin/AdminHandlersProxyTest.java
+++ 
b/solr/core/src/test/org/apache/solr/handler/admin/AdminHandlersProxyTest.java
@@ -57,7 +57,11 @@ public class AdminHandlersProxyTest extends 
SolrCloudTestCase {
   public void proxySystemInfoHandlerAllNodes() throws IOException, 
SolrServerException {
     MapSolrParams params = new MapSolrParams(Collections.singletonMap("nodes", 
"all"));
     GenericSolrRequest req =
-        new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/info/system", 
params);
+        new GenericSolrRequest(
+            SolrRequest.METHOD.GET,
+            "/admin/info/system",
+            SolrRequest.SolrRequestType.ADMIN,
+            params);
     SimpleSolrResponse rsp = req.process(solrClient, null);
     NamedList<Object> nl = rsp.getResponse();
     assertEquals(3, nl.size());
@@ -71,7 +75,8 @@ public class AdminHandlersProxyTest extends SolrCloudTestCase 
{
   public void proxyMetricsHandlerAllNodes() throws IOException, 
SolrServerException {
     MapSolrParams params = new MapSolrParams(Collections.singletonMap("nodes", 
"all"));
     GenericSolrRequest req =
-        new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/metrics", 
params);
+        new GenericSolrRequest(
+            SolrRequest.METHOD.GET, "/admin/metrics", 
SolrRequest.SolrRequestType.ADMIN, params);
     SimpleSolrResponse rsp = req.process(solrClient, null);
     NamedList<Object> nl = rsp.getResponse();
     assertEquals(3, nl.size());
@@ -85,7 +90,11 @@ public class AdminHandlersProxyTest extends 
SolrCloudTestCase {
     MapSolrParams params =
         new MapSolrParams(Collections.singletonMap("nodes", 
"example.com:1234_solr"));
     GenericSolrRequest req =
-        new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/info/system", 
params);
+        new GenericSolrRequest(
+            SolrRequest.METHOD.GET,
+            "/admin/info/system",
+            SolrRequest.SolrRequestType.ADMIN,
+            params);
     SimpleSolrResponse rsp = req.process(solrClient, null);
   }
 
@@ -97,7 +106,11 @@ public class AdminHandlersProxyTest extends 
SolrCloudTestCase {
         node -> {
           MapSolrParams params = new 
MapSolrParams(Collections.singletonMap("nodes", node));
           GenericSolrRequest req =
-              new GenericSolrRequest(SolrRequest.METHOD.GET, 
"/admin/info/system", params);
+              new GenericSolrRequest(
+                  SolrRequest.METHOD.GET,
+                  "/admin/info/system",
+                  SolrRequest.SolrRequestType.ADMIN,
+                  params);
           SimpleSolrResponse rsp = null;
           try {
             rsp = req.process(solrClient, null);
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/HealthCheckHandlerTest.java 
b/solr/core/src/test/org/apache/solr/handler/admin/HealthCheckHandlerTest.java
index 7607741f153..ced47e30c78 100644
--- 
a/solr/core/src/test/org/apache/solr/handler/admin/HealthCheckHandlerTest.java
+++ 
b/solr/core/src/test/org/apache/solr/handler/admin/HealthCheckHandlerTest.java
@@ -64,7 +64,8 @@ public class HealthCheckHandlerTest extends SolrCloudTestCase 
{
     // as compared with testHealthCheckHandlerWithCloudClient
     // (Not sure if that's actually a good thing -- but it's how the existing 
test worked)
     final var genericHealthcheck =
-        new GenericSolrRequest(SolrRequest.METHOD.GET, 
HEALTH_CHECK_HANDLER_PATH);
+        new GenericSolrRequest(
+            SolrRequest.METHOD.GET, HEALTH_CHECK_HANDLER_PATH, 
SolrRequest.SolrRequestType.ADMIN);
     assertEquals(
         CommonParams.OK,
         
genericHealthcheck.process(cluster.getSolrClient()).getResponse().get(CommonParams.STATUS));
diff --git 
a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java 
b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
index a4d38ccf68d..f52b76d5706 100644
--- 
a/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
+++ 
b/solr/core/src/test/org/apache/solr/response/TestPrometheusResponseWriter.java
@@ -30,8 +30,10 @@ import java.util.stream.Collectors;
 import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.solr.SolrTestCaseJ4;
 import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.impl.NoOpResponseParser;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.metrics.SolrMetricManager;
@@ -79,9 +81,8 @@ public class TestPrometheusResponseWriter extends 
SolrTestCaseJ4 {
   @Test
   public void testPrometheusStructureOutput() throws Exception {
     ModifiableSolrParams params = new ModifiableSolrParams();
-    params.set("qt", "/admin/metrics");
     params.set("wt", "prometheus");
-    QueryRequest req = new QueryRequest(params);
+    var req = new GenericSolrRequest(METHOD.GET, "/admin/metrics", 
SolrRequestType.ADMIN, params);
     req.setResponseParser(new NoOpResponseParser("prometheus"));
 
     try (SolrClient adminClient = 
getHttpSolrClient(solrClientTestRule.getBaseUrl())) {
@@ -135,9 +136,8 @@ public class TestPrometheusResponseWriter extends 
SolrTestCaseJ4 {
     String expectedJvm = "solr_metrics_jvm_gc{item=\"dummyMetrics\"} 0.0";
 
     ModifiableSolrParams params = new ModifiableSolrParams();
-    params.set("qt", "/admin/metrics");
     params.set("wt", "prometheus");
-    QueryRequest req = new QueryRequest(params);
+    var req = new GenericSolrRequest(METHOD.GET, "/admin/metrics", 
SolrRequestType.ADMIN, params);
     req.setResponseParser(new NoOpResponseParser("prometheus"));
 
     try (SolrClient adminClient = 
getHttpSolrClient(solrClientTestRule.getBaseUrl())) {
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 77ee3536959..22f5f4a6857 100644
--- a/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
+++ b/solr/core/src/test/org/apache/solr/security/BasicAuthIntegrationTest.java
@@ -142,7 +142,8 @@ public class BasicAuthIntegrationTest extends 
SolrCloudAuthTestCase {
                 .build();
       } else {
         GenericSolrRequest genericSolrRequest =
-            new GenericSolrRequest(SolrRequest.METHOD.POST, authcPrefix);
+            new GenericSolrRequest(
+                SolrRequest.METHOD.POST, authcPrefix, 
SolrRequest.SolrRequestType.ADMIN);
         genericSolrRequest.setContentWriter(
             new StringPayloadContentWriter(command, CommonParams.JSON_MIME));
         genericReq = genericSolrRequest;
diff --git 
a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java
 
b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java
index d16e60bcf17..711c1039a6d 100644
--- 
a/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java
+++ 
b/solr/modules/opentelemetry/src/test/org/apache/solr/opentelemetry/TestDistributedTracing.java
@@ -29,6 +29,7 @@ import java.util.List;
 import java.util.Map;
 import org.apache.solr.client.solrj.SolrQuery;
 import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
@@ -129,7 +130,8 @@ public class TestDistributedTracing extends 
SolrCloudTestCase {
   public void testAdminApi() throws Exception {
     CloudSolrClient cloudClient = cluster.getSolrClient();
 
-    cloudClient.request(new GenericSolrRequest(SolrRequest.METHOD.GET, 
"/admin/metrics"));
+    cloudClient.request(
+        new GenericSolrRequest(SolrRequest.METHOD.GET, "/admin/metrics", 
SolrRequestType.ADMIN));
     var finishedSpans = getAndClearSpans();
     assertEquals("get:/admin/metrics", finishedSpans.get(0).getName());
 
diff --git 
a/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/scraper/SolrScraper.java
 
b/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/scraper/SolrScraper.java
index 5bc4d720b1b..60e6cf87a18 100644
--- 
a/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/scraper/SolrScraper.java
+++ 
b/solr/prometheus-exporter/src/java/org/apache/solr/prometheus/scraper/SolrScraper.java
@@ -16,6 +16,8 @@
  */
 package org.apache.solr.prometheus.scraper;
 
+import static org.apache.solr.common.params.CommonParams.ADMIN_PATHS;
+
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import io.prometheus.client.Collector;
@@ -35,10 +37,12 @@ import java.util.stream.Collectors;
 import net.thisptr.jackson.jq.JsonQuery;
 import net.thisptr.jackson.jq.exception.JsonQueryException;
 import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.Http2SolrClient;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.prometheus.collector.MetricSamples;
 import org.apache.solr.prometheus.exporter.MetricsQuery;
@@ -130,29 +134,38 @@ public abstract class SolrScraper implements Closeable {
       zkHostLabelValue = ((CloudSolrClient) 
client).getClusterStateProvider().getQuorumHosts();
     }
 
-    QueryRequest queryRequest = new QueryRequest(query.getParameters());
-    queryRequest.setPath(query.getPath());
+    GenericSolrRequest request = null;
+    if (ADMIN_PATHS.contains(query.getPath())) {
+      request =
+          new GenericSolrRequest(
+              METHOD.GET, query.getPath(), SolrRequestType.ADMIN, 
query.getParameters());
+    } else {
+      request =
+          new GenericSolrRequest(
+              METHOD.GET, query.getPath(), SolrRequestType.ADMIN, 
query.getParameters());
+      request.setRequiresCollection(true);
+    }
 
-    NamedList<Object> queryResponse;
+    NamedList<Object> response;
     try {
       if (query.getCollection().isEmpty() && query.getCore().isEmpty()) {
-        queryResponse = client.request(queryRequest);
+        response = client.request(request);
       } else if (query.getCore().isPresent()) {
-        queryResponse = client.request(queryRequest, query.getCore().get());
+        response = client.request(request, query.getCore().get());
       } else if (query.getCollection().isPresent()) {
-        queryResponse = client.request(queryRequest, 
query.getCollection().get());
+        response = client.request(request, query.getCollection().get());
       } else {
         throw new AssertionError("Invalid configuration");
       }
-      if (queryResponse == null) { // ideally we'd make this impossible
+      if (response == null) { // ideally we'd make this impossible
         throw new RuntimeException("no response from server");
       }
     } catch (SolrServerException | IOException e) {
-      log.error("failed to request: {}", queryRequest.getPath(), e);
+      log.error("failed to request: {}", request.getPath(), e);
       return samples;
     }
 
-    JsonNode jsonNode = OBJECT_MAPPER.readTree((String) 
queryResponse.get("response"));
+    JsonNode jsonNode = OBJECT_MAPPER.readTree((String) 
response.get("response"));
 
     for (JsonQuery jsonQuery : query.getJsonQueries()) {
       try {
diff --git a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
index d3877dc091a..e506d3cb62a 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
@@ -26,6 +26,7 @@ import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
+import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.request.RequestWriter;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.ContentStream;
@@ -99,6 +100,7 @@ public abstract class SolrRequest<T> implements Serializable 
{
 
   private METHOD method = METHOD.GET;
   private String path = null;
+  private SolrRequestType requestType = SolrRequestType.UNSPECIFIED;
   private Map<String, String> headers;
   private List<String> preferredNodes;
 
@@ -136,9 +138,10 @@ public abstract class SolrRequest<T> implements 
Serializable {
   // ---------------------------------------------------------
   // ---------------------------------------------------------
 
-  public SolrRequest(METHOD m, String path) {
+  public SolrRequest(METHOD m, String path, SolrRequestType requestType) {
     this.method = m;
     this.path = path;
+    this.requestType = requestType;
   }
 
   // ---------------------------------------------------------
@@ -194,8 +197,20 @@ public abstract class SolrRequest<T> implements 
Serializable {
     this.queryParams = queryParams;
   }
 
-  /** This method defines the type of this Solr request. */
-  public abstract String getRequestType();
+  /**
+   * The type of this Solr request.
+   *
+   * <p>Pattern matches {@link SolrRequest#getPath} to identify ADMIN requests 
and other special
+   * cases. Overriding this method may affect request routing within various 
clients (i.e. {@link
+   * CloudSolrClient}).
+   */
+  public SolrRequestType getRequestType() {
+    return requestType;
+  }
+
+  public void setRequestType(SolrRequestType requestType) {
+    this.requestType = requestType;
+  }
 
   /**
    * The parameters for this request; never null. The runtime type may be 
mutable but modifications
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 8a7bddd0ad1..c30ed4165c6 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
@@ -17,7 +17,6 @@
 
 package org.apache.solr.client.solrj.impl;
 
-import static org.apache.solr.common.params.CommonParams.ADMIN_PATHS;
 import static org.apache.solr.common.params.CommonParams.ID;
 
 import java.io.IOException;
@@ -51,9 +50,8 @@ import java.util.stream.Collectors;
 import org.apache.solr.client.solrj.ResponseParser;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
-import org.apache.solr.client.solrj.request.IsUpdateRequest;
 import org.apache.solr.client.solrj.request.RequestWriter;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.request.V2Request;
@@ -355,9 +353,8 @@ public abstract class CloudSolrClient extends SolrClient {
   }
 
   @SuppressWarnings({"unchecked"})
-  private NamedList<Object> directUpdate(AbstractUpdateRequest request, String 
collection)
+  private NamedList<Object> directUpdate(UpdateRequest request, String 
collection)
       throws SolrServerException {
-    UpdateRequest updateRequest = (UpdateRequest) request;
     SolrParams params = request.getParams();
     ModifiableSolrParams routableParams = new ModifiableSolrParams();
     ModifiableSolrParams nonRoutableParams = new ModifiableSolrParams();
@@ -411,9 +408,9 @@ public abstract class CloudSolrClient extends SolrClient {
     String routeField =
         (col.getRouter().getRouteField(col) == null) ? ID : 
col.getRouter().getRouteField(col);
     final Map<String, ? extends LBSolrClient.Req> routes =
-        createRoutes(updateRequest, routableParams, col, router, urlMap, 
routeField);
+        createRoutes(request, routableParams, col, router, urlMap, routeField);
     if (routes == null) {
-      if (directUpdatesToLeadersOnly && hasInfoToFindLeaders(updateRequest, 
routeField)) {
+      if (directUpdatesToLeadersOnly && hasInfoToFindLeaders(request, 
routeField)) {
         // we have info (documents with ids and/or ids to delete) with
         // which to find the leaders, but we could not find (all of) them
         throw new SolrException(
@@ -490,7 +487,7 @@ public abstract class CloudSolrClient extends SolrClient {
     }
 
     UpdateRequest nonRoutableRequest = null;
-    List<String> deleteQuery = updateRequest.getDeleteQuery();
+    List<String> deleteQuery = request.getDeleteQuery();
     if (deleteQuery != null && deleteQuery.size() > 0) {
       UpdateRequest deleteQueryRequest = new UpdateRequest();
       deleteQueryRequest.setDeleteQuery(deleteQuery);
@@ -799,7 +796,8 @@ public abstract class CloudSolrClient extends SolrClient {
     if (request instanceof V2Request) {
       isCollectionRequestOfV2 = ((V2Request) request).isPerCollectionRequest();
     }
-    boolean isAdmin = ADMIN_PATHS.contains(request.getPath());
+    boolean isAdmin =
+        request.getRequestType() == SolrRequestType.ADMIN && 
!request.requiresCollection();
     if (!inputCollections.isEmpty()
         && !isAdmin
         && !isCollectionRequestOfV2) { // don't do _stateVer_ checking for 
admin, v2 api requests
@@ -1000,25 +998,29 @@ public abstract class CloudSolrClient extends SolrClient 
{
 
     boolean sendToLeaders = false;
 
-    if (request instanceof IsUpdateRequest) {
-      sendToLeaders = ((IsUpdateRequest) request).isSendToLeaders() && 
this.isUpdatesToLeaders();
+    if (request.getRequestType() == SolrRequestType.UPDATE) {
+      sendToLeaders = this.isUpdatesToLeaders();
 
-      // Check if we can do a "directUpdate" ...
-      if (sendToLeaders && request instanceof UpdateRequest) {
-        if (inputCollections.size() > 1) {
-          throw new SolrException(
-              SolrException.ErrorCode.BAD_REQUEST,
-              "Update request must be sent to a single collection "
-                  + "or an alias: "
-                  + inputCollections);
-        }
-        String collection =
-            inputCollections.isEmpty()
-                ? null
-                : inputCollections.get(0); // getting first mimics HttpSolrCall
-        NamedList<Object> response = directUpdate((AbstractUpdateRequest) 
request, collection);
-        if (response != null) {
-          return response;
+      if (sendToLeaders && request instanceof UpdateRequest updateRequest) {
+        sendToLeaders = sendToLeaders && updateRequest.isSendToLeaders();
+
+        // Check if we can do a "directUpdate" ...
+        if (sendToLeaders) {
+          if (inputCollections.size() > 1) {
+            throw new SolrException(
+                SolrException.ErrorCode.BAD_REQUEST,
+                "Update request must be sent to a single collection "
+                    + "or an alias: "
+                    + inputCollections);
+          }
+          String collection =
+              inputCollections.isEmpty()
+                  ? null
+                  : inputCollections.get(0); // getting first mimics 
HttpSolrCall
+          NamedList<Object> response = directUpdate(updateRequest, collection);
+          if (response != null) {
+            return response;
+          }
         }
       }
     }
@@ -1044,13 +1046,13 @@ public abstract class CloudSolrClient extends 
SolrClient {
         requestEndpoints.add(new LBSolrClient.Endpoint(chosenNodeUrl));
       }
 
-    } else if (ADMIN_PATHS.contains(request.getPath())) {
+    } else if (!request.requiresCollection()) {
       for (String liveNode : liveNodes) {
         final var nodeBaseUrl = Utils.getBaseUrlForNodeName(liveNode, 
urlScheme);
         requestEndpoints.add(new LBSolrClient.Endpoint(nodeBaseUrl));
       }
-
-    } else { // Typical...
+    } else { // API call to a particular collection / core / alias (i.e.
+      // request.requiresCollection() == true)
       Set<String> collectionNames = resolveAliases(inputCollections);
       if (collectionNames.isEmpty()) {
         throw new SolrException(
@@ -1172,9 +1174,9 @@ public abstract class CloudSolrClient extends SolrClient {
 
   /**
    * If true, this client has been configured such that it will generally 
prefer to send {@link
-   * IsUpdateRequest} requests to a shard leader, if and only if {@link
-   * IsUpdateRequest#isSendToLeaders} is also true. If false, then this client 
has been configured
-   * to obey normal routing preferences when dealing with {@link 
IsUpdateRequest} requests.
+   * SolrRequestType#UPDATE} requests to a shard leader, if and only if {@link
+   * UpdateRequest#isSendToLeaders} is also true. If false, then this client 
has been configured to
+   * obey normal routing preferences when dealing with {@link 
SolrRequestType#UPDATE} requests.
    *
    * @see #isDirectUpdatesToLeadersOnly
    */
@@ -1186,7 +1188,7 @@ public abstract class CloudSolrClient extends SolrClient {
    * If true, this client has been configured such that "direct updates" will 
<em>only</em> be sent
    * to the current leader of the corresponding shard, and will not be retried 
with other replicas.
    * This method has no effect if {@link #isUpdatesToLeaders()} or {@link
-   * IsUpdateRequest#isSendToLeaders} returns false.
+   * UpdateRequest#isSendToLeaders} returns false.
    *
    * <p>A "direct update" is any update that can be sent directly to a single 
shard, and does not
    * need to be broadcast to every shard. (Example: document updates or 
"delete by id" when using
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 e1de05d97da..1bea292b042 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
@@ -752,7 +752,7 @@ public class HttpSolrClient extends BaseHttpSolrClient {
         new BasicHeader(CommonParams.SOLR_REQUEST_CONTEXT_PARAM, 
getContext().toString());
 
     contextHeaders[1] =
-        new BasicHeader(CommonParams.SOLR_REQUEST_TYPE_PARAM, 
request.getRequestType());
+        new BasicHeader(CommonParams.SOLR_REQUEST_TYPE_PARAM, 
request.getRequestType().toString());
 
     return contextHeaders;
   }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttp2SolrClient.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttp2SolrClient.java
index 33488a83d30..ab31fe7a482 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttp2SolrClient.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBHttp2SolrClient.java
@@ -16,8 +16,6 @@
  */
 package org.apache.solr.client.solrj.impl;
 
-import static org.apache.solr.common.params.CommonParams.ADMIN_PATHS;
-
 import java.io.IOException;
 import java.net.ConnectException;
 import java.net.SocketException;
@@ -29,8 +27,8 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicReference;
 import org.apache.solr.client.solrj.ResponseParser;
 import org.apache.solr.client.solrj.SolrClient;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 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.common.SolrException;
 import org.apache.solr.common.util.NamedList;
@@ -138,8 +136,9 @@ public class LBHttp2SolrClient<C extends 
HttpSolrClientBase> extends LBSolrClien
   public CompletableFuture<Rsp> requestAsync(Req req) {
     CompletableFuture<Rsp> apiFuture = new CompletableFuture<>();
     Rsp rsp = new Rsp();
-    boolean isNonRetryable =
-        req.request instanceof IsUpdateRequest || 
ADMIN_PATHS.contains(req.request.getPath());
+    boolean isAdmin =
+        req.request.getRequestType() == SolrRequestType.ADMIN && 
!req.request.requiresCollection();
+    boolean isNonRetryable = req.request.getRequestType() == 
SolrRequestType.UPDATE || isAdmin;
     EndpointIterator it = new EndpointIterator(req, zombieServers);
     AtomicReference<CompletableFuture<NamedList<Object>>> currentFuture = new 
AtomicReference<>();
     RetryListener retryListener =
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
index 0d0d539d97c..ebe6a0ed588 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/impl/LBSolrClient.java
@@ -17,8 +17,6 @@
 
 package org.apache.solr.client.solrj.impl;
 
-import static org.apache.solr.common.params.CommonParams.ADMIN_PATHS;
-
 import java.io.IOException;
 import java.lang.invoke.MethodHandles;
 import java.lang.ref.WeakReference;
@@ -46,8 +44,8 @@ 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.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
-import org.apache.solr.client.solrj.request.IsUpdateRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.RequestWriter;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -456,8 +454,9 @@ public abstract class LBSolrClient extends SolrClient {
   public Rsp request(Req req) throws SolrServerException, IOException {
     Rsp rsp = new Rsp();
     Exception ex = null;
-    boolean isNonRetryable =
-        req.request instanceof IsUpdateRequest || 
ADMIN_PATHS.contains(req.request.getPath());
+    boolean isAdmin =
+        req.request.getRequestType() == SolrRequestType.ADMIN && 
!req.request.requiresCollection();
+    boolean isNonRetryable = req.request.getRequestType() == 
SolrRequestType.UPDATE || isAdmin;
     EndpointIterator endpointIterator = new EndpointIterator(req, 
zombieServers);
     Endpoint serverStr;
     while ((serverStr = endpointIterator.nextOrError(ex)) != null) {
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/AbstractUpdateRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/AbstractUpdateRequest.java
index aaf7433c39b..86ad02c16ab 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/AbstractUpdateRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/AbstractUpdateRequest.java
@@ -22,8 +22,7 @@ import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.UpdateParams;
 import org.apache.solr.common.util.NamedList;
 
-public abstract class AbstractUpdateRequest extends 
CollectionRequiringSolrRequest<UpdateResponse>
-    implements IsUpdateRequest {
+public abstract class AbstractUpdateRequest extends 
CollectionRequiringSolrRequest<UpdateResponse> {
   protected ModifiableSolrParams params = new ModifiableSolrParams(); // maybe 
make final; no setter
   protected int commitWithin = -1;
 
@@ -33,7 +32,7 @@ public abstract class AbstractUpdateRequest extends 
CollectionRequiringSolrReque
   }
 
   public AbstractUpdateRequest(METHOD m, String path) {
-    super(m, path);
+    super(m, path, SolrRequestType.UPDATE);
   }
 
   /** Sets appropriate parameters for the given ACTION */
@@ -125,11 +124,6 @@ public abstract class AbstractUpdateRequest extends 
CollectionRequiringSolrReque
     return new UpdateResponse();
   }
 
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.UPDATE.toString();
-  }
-
   public boolean isWaitSearcher() {
     return params.getBool(UpdateParams.WAIT_SEARCHER, false);
   }
@@ -152,16 +146,4 @@ public abstract class AbstractUpdateRequest extends 
CollectionRequiringSolrReque
     this.commitWithin = commitWithin;
     return this;
   }
-
-  private boolean sendToLeaders = true;
-
-  @Override
-  public boolean isSendToLeaders() {
-    return sendToLeaders;
-  }
-
-  public AbstractUpdateRequest setSendToLeaders(final boolean sendToLeaders) {
-    this.sendToLeaders = sendToLeaders;
-    return this;
-  }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
index 8a6f30bc411..3bff75b840e 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionAdminRequest.java
@@ -85,7 +85,7 @@ public abstract class CollectionAdminRequest<T extends 
CollectionAdminResponse>
   }
 
   public CollectionAdminRequest(String path, CollectionAction action) {
-    super(METHOD.GET, path);
+    super(METHOD.GET, path, SolrRequestType.ADMIN);
     this.action = checkNotNull(CoreAdminParams.ACTION, action);
   }
 
@@ -124,8 +124,8 @@ public abstract class CollectionAdminRequest<T extends 
CollectionAdminResponse>
   }
 
   @Override
-  public String getRequestType() {
-    return SolrRequestType.ADMIN.toString();
+  public boolean requiresCollection() {
+    return false;
   }
 
   /**
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionRequiringSolrRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionRequiringSolrRequest.java
index fb31982f61a..871d90f49d4 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionRequiringSolrRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CollectionRequiringSolrRequest.java
@@ -20,8 +20,8 @@ import org.apache.solr.client.solrj.SolrRequest;
 
 /** Parent {@link SolrRequest} class that requires a target collection or 
core. */
 public abstract class CollectionRequiringSolrRequest<T> extends SolrRequest<T> 
{
-  public CollectionRequiringSolrRequest(METHOD m, String path) {
-    super(m, path);
+  public CollectionRequiringSolrRequest(METHOD m, String path, SolrRequestType 
requestType) {
+    super(m, path, requestType);
   }
 
   @Override
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/ConfigSetAdminRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/ConfigSetAdminRequest.java
index 37c6b310055..f11da334c47 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/ConfigSetAdminRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/ConfigSetAdminRequest.java
@@ -52,11 +52,11 @@ public abstract class ConfigSetAdminRequest<
   }
 
   public ConfigSetAdminRequest() {
-    super(METHOD.GET, "/admin/configs");
+    super(METHOD.GET, "/admin/configs", SolrRequestType.ADMIN);
   }
 
   public ConfigSetAdminRequest(String path) {
-    super(METHOD.GET, path);
+    super(METHOD.GET, path, SolrRequestType.ADMIN);
   }
 
   protected abstract Q getThis();
@@ -104,11 +104,6 @@ public abstract class ConfigSetAdminRequest<
     }
   }
 
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.ADMIN.toString();
-  }
-
   /**
    * Uploads files to create a new configset, or modify an existing config set.
    *
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java
index 18ca8887dad..72c39c08da8 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/CoreAdminRequest.java
@@ -45,11 +45,6 @@ public class CoreAdminRequest extends 
SolrRequest<CoreAdminResponse> {
   protected boolean isIndexInfoNeeded = true;
   protected CoreAdminParams.CoreAdminAction action = null;
 
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.ADMIN.toString();
-  }
-
   // a create core request
   public static class Create extends CoreAdminRequest {
 
@@ -591,11 +586,11 @@ public class CoreAdminRequest extends 
SolrRequest<CoreAdminResponse> {
   }
 
   public CoreAdminRequest() {
-    super(METHOD.GET, "/admin/cores");
+    super(METHOD.GET, "/admin/cores", SolrRequestType.ADMIN);
   }
 
   public CoreAdminRequest(String path) {
-    super(METHOD.GET, path);
+    super(METHOD.GET, path, SolrRequestType.ADMIN);
   }
 
   public void setCoreName(String coreName) {
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/DelegationTokenRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/DelegationTokenRequest.java
index 6fc9d47e98d..fc7a6a38cd3 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/DelegationTokenRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/DelegationTokenRequest.java
@@ -43,7 +43,7 @@ public abstract class DelegationTokenRequest<
     // path doesn't really matter -- the filter will respond to any path.
     // setting the path to admin/collections lets us pass through 
CloudSolrServer
     // without having to specify a collection (that may not even exist yet).
-    super(m, "/admin/collections");
+    super(m, "/admin/collections", SolrRequestType.ADMIN);
   }
 
   protected abstract Q getThis();
@@ -82,11 +82,6 @@ public abstract class DelegationTokenRequest<
     public DelegationTokenResponse.Get createResponse(NamedList<Object> 
namedList) {
       return new DelegationTokenResponse.Get();
     }
-
-    @Override
-    public String getRequestType() {
-      return SolrRequestType.ADMIN.toString();
-    }
   }
 
   public static class Renew extends DelegationTokenRequest<Renew, 
DelegationTokenResponse.Renew> {
@@ -116,11 +111,6 @@ public abstract class DelegationTokenRequest<
     public DelegationTokenResponse.Renew createResponse(NamedList<Object> 
namedList) {
       return new DelegationTokenResponse.Renew();
     }
-
-    @Override
-    public String getRequestType() {
-      return SolrRequestType.ADMIN.toString();
-    }
   }
 
   public static class Cancel
@@ -151,10 +141,5 @@ public abstract class DelegationTokenRequest<
     public DelegationTokenResponse.Cancel createResponse(NamedList<Object> 
namedList) {
       return new DelegationTokenResponse.Cancel();
     }
-
-    @Override
-    public String getRequestType() {
-      return SolrRequestType.ADMIN.toString();
-    }
   }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/DirectXmlRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/DirectXmlRequest.java
index 88ce4b17f14..18878735e2f 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/DirectXmlRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/DirectXmlRequest.java
@@ -37,7 +37,7 @@ public class DirectXmlRequest extends 
CollectionRequiringSolrRequest<UpdateRespo
   private SolrParams params;
 
   public DirectXmlRequest(String path, String body) {
-    super(METHOD.POST, path);
+    super(METHOD.POST, path, SolrRequestType.UPDATE);
     xml = body;
   }
 
@@ -56,11 +56,6 @@ public class DirectXmlRequest extends 
CollectionRequiringSolrRequest<UpdateRespo
     return params != null ? params : new ModifiableSolrParams();
   }
 
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.UPDATE.toString();
-  }
-
   public void setParams(SolrParams params) {
     this.params = params;
   }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/DocumentAnalysisRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/DocumentAnalysisRequest.java
index ce93f0f6f29..d1d5c67222e 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/DocumentAnalysisRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/DocumentAnalysisRequest.java
@@ -47,7 +47,7 @@ public class DocumentAnalysisRequest
 
   /** Constructs a new request with a default uri of "/documentanalysis". */
   public DocumentAnalysisRequest() {
-    super(METHOD.POST, "/analysis/document");
+    super(METHOD.POST, "/analysis/document", SolrRequestType.QUERY);
   }
 
   /**
@@ -56,7 +56,7 @@ public class DocumentAnalysisRequest
    * @param uri The of the request handler.
    */
   public DocumentAnalysisRequest(String uri) {
-    super(METHOD.POST, uri);
+    super(METHOD.POST, uri, SolrRequestType.QUERY);
   }
 
   @Override
@@ -197,9 +197,4 @@ public class DocumentAnalysisRequest
   public boolean isShowMatch() {
     return showMatch;
   }
-
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.QUERY.toString();
-  }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/FieldAnalysisRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/FieldAnalysisRequest.java
index 00e49e64130..116a80a4ec7 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/FieldAnalysisRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/FieldAnalysisRequest.java
@@ -39,7 +39,7 @@ public class FieldAnalysisRequest extends 
CollectionRequiringSolrRequest<FieldAn
 
   /** Constructs a new FieldAnalysisRequest with a default uri of 
"/fieldanalysis". */
   public FieldAnalysisRequest() {
-    super(METHOD.GET, "/analysis/field");
+    super(METHOD.GET, "/analysis/field", SolrRequestType.QUERY);
   }
 
   /**
@@ -48,7 +48,7 @@ public class FieldAnalysisRequest extends 
CollectionRequiringSolrRequest<FieldAn
    * @param uri the uri of the request handler.
    */
   public FieldAnalysisRequest(String uri) {
-    super(METHOD.GET, uri);
+    super(METHOD.GET, uri, SolrRequestType.QUERY);
   }
 
   @Override
@@ -81,11 +81,6 @@ public class FieldAnalysisRequest extends 
CollectionRequiringSolrRequest<FieldAn
     return params;
   }
 
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.QUERY.toString();
-  }
-
   // ===== Helper Methods =====
 
   /**
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/GenericSolrRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/GenericSolrRequest.java
index 599a6a3d897..24edb9b320a 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/GenericSolrRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/GenericSolrRequest.java
@@ -42,6 +42,17 @@ public class GenericSolrRequest extends 
SolrRequest<SimpleSolrResponse> {
     this(m, path, new ModifiableSolrParams());
   }
 
+  /**
+   * @param m the HTTP method to use for this request
+   * @param path the HTTP path to use for this request. If users are making a 
collection-aware
+   *     request (i.e. {@link #setRequiresCollection(boolean)} is called with 
'true'), only the
+   *     section of the API path following the collection or core should be 
provided here.
+   * @param requestType the type of this request
+   */
+  public GenericSolrRequest(METHOD m, String path, SolrRequestType 
requestType) {
+    this(m, path, requestType, new ModifiableSolrParams());
+  }
+
   /**
    * @param m the HTTP method to use for this request
    * @param path the HTTP path to use for this request. If users are making a 
collection-aware
@@ -50,7 +61,20 @@ public class GenericSolrRequest extends 
SolrRequest<SimpleSolrResponse> {
    * @param params query parameter names and values for making this request.
    */
   public GenericSolrRequest(METHOD m, String path, SolrParams params) {
-    super(m, path);
+    super(m, path, SolrRequestType.UNSPECIFIED);
+    this.params = Objects.requireNonNull(params);
+  }
+
+  /**
+   * @param m the HTTP method to use for this request
+   * @param path the HTTP path to use for this request. If users are making a 
collection-aware
+   *     request (i.e. {@link #setRequiresCollection(boolean)} is called with 
'true'), only the
+   *     section of the API path following the collection or core should be 
provided here.
+   * @param requestType the type of this request
+   * @param params query parameter names and values for making this request.
+   */
+  public GenericSolrRequest(METHOD m, String path, SolrRequestType 
requestType, SolrParams params) {
+    super(m, path, requestType);
     this.params = Objects.requireNonNull(params);
   }
 
@@ -107,9 +131,4 @@ public class GenericSolrRequest extends 
SolrRequest<SimpleSolrResponse> {
   protected SimpleSolrResponse createResponse(NamedList<Object> namedList) {
     return response;
   }
-
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.UNSPECIFIED.toString();
-  }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/GenericV2SolrRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/GenericV2SolrRequest.java
index d17a549299c..2028e37471b 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/GenericV2SolrRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/GenericV2SolrRequest.java
@@ -32,6 +32,18 @@ public class GenericV2SolrRequest extends GenericSolrRequest 
{
     super(m, removeLeadingApiRoot(path));
   }
 
+  /**
+   * @param m the HTTP method to use for this request
+   * @param path the HTTP path to use for this request. Path may include the 
v2 API root path (i.e.
+   *     "/api"), but does not need to. If users are making a collection-aware 
request (i.e. {@link
+   *     #setRequiresCollection(boolean)} is called with 'true'), only the 
section of the API path
+   *     following the collection or core should be provided here.
+   * @param requestType the type of this request
+   */
+  public GenericV2SolrRequest(METHOD m, String path, SolrRequestType 
requestType) {
+    super(m, removeLeadingApiRoot(path), requestType);
+  }
+
   /**
    * @param m the HTTP method to use for this request
    * @param path the HTTP path to use for this request. If users are making a 
collection-aware
@@ -43,6 +55,19 @@ public class GenericV2SolrRequest extends GenericSolrRequest 
{
     super(m, removeLeadingApiRoot(path), params);
   }
 
+  /**
+   * @param m the HTTP method to use for this request
+   * @param path the HTTP path to use for this request. If users are making a 
collection-aware
+   *     request (i.e. {@link #setRequiresCollection(boolean)} is called with 
'true'), only the
+   *     section of the API path following the collection or core should be 
provided here.
+   * @param requestType the type of this request
+   * @param params query parameter names and values for making this request.
+   */
+  public GenericV2SolrRequest(
+      METHOD m, String path, SolrRequestType requestType, SolrParams params) {
+    super(m, removeLeadingApiRoot(path), requestType, params);
+  }
+
   @Override
   public ApiVersion getApiVersion() {
     return ApiVersion.V2;
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/HealthCheckRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/HealthCheckRequest.java
index 44854975991..5493024cf03 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/HealthCheckRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/HealthCheckRequest.java
@@ -36,7 +36,7 @@ public class HealthCheckRequest extends 
SolrRequest<HealthCheckResponse> {
   }
 
   private HealthCheckRequest(METHOD m, String path) {
-    super(m, path);
+    super(m, path, SolrRequestType.ADMIN);
   }
 
   public void setMaxGenerationLag(int maxLagAllowed) {
@@ -58,9 +58,4 @@ public class HealthCheckRequest extends 
SolrRequest<HealthCheckResponse> {
     // to an unintended recipient.
     return new HealthCheckResponse();
   }
-
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.ADMIN.toString();
-  }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/IsUpdateRequest.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/IsUpdateRequest.java
index 54f449e1358..aa18874c4ba 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/IsUpdateRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/IsUpdateRequest.java
@@ -16,9 +16,15 @@
  */
 package org.apache.solr.client.solrj.request;
 
+import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 
-/** Marker class so that we can determine which requests are updates. */
+/**
+ * Marker class so that we can determine which requests are updates.
+ *
+ * @deprecated Use {@link UpdateRequest#isSendToLeaders} and {@link 
SolrRequest#getRequestType}.
+ */
+@Deprecated
 public interface IsUpdateRequest {
 
   /**
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/LukeRequest.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/LukeRequest.java
index e090d953670..243d811e5d7 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/LukeRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/LukeRequest.java
@@ -35,11 +35,12 @@ public class LukeRequest extends 
CollectionRequiringSolrRequest<LukeResponse> {
   private Boolean includeIndexFieldFlags = null;
 
   public LukeRequest() {
-    super(METHOD.GET, "/admin/luke");
+    // this request is not processed as an ADMIN request
+    super(METHOD.GET, "/admin/luke", SolrRequestType.ADMIN);
   }
 
   public LukeRequest(String path) {
-    super(METHOD.GET, path);
+    super(METHOD.GET, path, SolrRequestType.ADMIN);
   }
 
   // 
---------------------------------------------------------------------------------
@@ -124,9 +125,4 @@ public class LukeRequest extends 
CollectionRequiringSolrRequest<LukeResponse> {
 
     return params;
   }
-
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.ADMIN.toString();
-  }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/QueryRequest.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/QueryRequest.java
index 047d24fe248..de3cdd78b9a 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/QueryRequest.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/QueryRequest.java
@@ -30,17 +30,17 @@ public class QueryRequest extends 
CollectionRequiringSolrRequest<QueryResponse>
   private final SolrParams query;
 
   public QueryRequest() {
-    super(METHOD.GET, null);
+    super(METHOD.GET, null, SolrRequestType.QUERY);
     query = SolrParams.of();
   }
 
   public QueryRequest(SolrParams q) {
-    super(METHOD.GET, null);
+    super(METHOD.GET, null, SolrRequestType.QUERY);
     query = Objects.requireNonNull(q);
   }
 
   public QueryRequest(SolrParams q, METHOD method) {
-    super(method, null);
+    super(method, null, SolrRequestType.QUERY);
     query = Objects.requireNonNull(q);
   }
 
@@ -69,9 +69,4 @@ public class QueryRequest extends 
CollectionRequiringSolrRequest<QueryResponse>
   public SolrParams getParams() {
     return query;
   }
-
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.QUERY.toString();
-  }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/SolrPing.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/SolrPing.java
index 609c286969c..2b9f9824802 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/SolrPing.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/SolrPing.java
@@ -38,7 +38,7 @@ public class SolrPing extends 
CollectionRequiringSolrRequest<SolrPingResponse> {
 
   /** Create a new SolrPing object. */
   public SolrPing() {
-    super(METHOD.GET, CommonParams.PING_HANDLER);
+    super(METHOD.GET, CommonParams.PING_HANDLER, SolrRequestType.ADMIN);
     params = new ModifiableSolrParams();
   }
 
@@ -52,11 +52,6 @@ public class SolrPing extends 
CollectionRequiringSolrRequest<SolrPingResponse> {
     return params;
   }
 
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.ADMIN.toString();
-  }
-
   /**
    * Remove the action parameter from this request. This will result in the 
same behavior as {@code
    * SolrPing#setActionPing()}. For Solr server version 4.0 and later.
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java
index 21c72fd7348..2d4e4e011d4 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/UpdateRequest.java
@@ -55,6 +55,7 @@ public class UpdateRequest extends AbstractUpdateRequest {
   private Iterator<SolrInputDocument> docIterator = null;
   private Map<String, Map<String, Object>> deleteById = null;
   private List<String> deleteQuery = null;
+  private boolean sendToLeaders = true;
 
   private boolean isLastDocInBatch = false;
 
@@ -390,4 +391,13 @@ public class UpdateRequest extends AbstractUpdateRequest {
   public void lastDocInBatch() {
     isLastDocInBatch = true;
   }
+
+  public boolean isSendToLeaders() {
+    return sendToLeaders;
+  }
+
+  public UpdateRequest setSendToLeaders(final boolean sendToLeaders) {
+    this.sendToLeaders = sendToLeaders;
+    return this;
+  }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java
index f73301c7f35..13a804b6592 100644
--- a/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java
+++ b/solr/solrj/src/java/org/apache/solr/client/solrj/request/V2Request.java
@@ -50,7 +50,7 @@ public class V2Request extends SolrRequest<V2Response> 
implements MapWriter {
   private ResponseParser parser;
 
   private V2Request(METHOD m, String resource, boolean useBinary) {
-    super(m, resource);
+    super(m, resource, SolrRequestType.ADMIN);
     Matcher matcher = COLL_REQ_PATTERN.matcher(getPath());
     if (matcher.find()) {
       this.collection = matcher.group(2);
@@ -105,6 +105,11 @@ public class V2Request extends SolrRequest<V2Response> 
implements MapWriter {
     return isPerCollectionRequest;
   }
 
+  @Override
+  public boolean requiresCollection() {
+    return isPerCollectionRequest;
+  }
+
   @Override
   public String getCollection() {
     return collection;
@@ -134,11 +139,6 @@ public class V2Request extends SolrRequest<V2Response> 
implements MapWriter {
     return super.getResponseParser();
   }
 
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.ADMIN.toString();
-  }
-
   public static class Builder {
     private String resource;
     private METHOD method = METHOD.GET;
diff --git 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/schema/AbstractSchemaRequest.java
 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/schema/AbstractSchemaRequest.java
index 1547e13d1a1..ea32f148b22 100644
--- 
a/solr/solrj/src/java/org/apache/solr/client/solrj/request/schema/AbstractSchemaRequest.java
+++ 
b/solr/solrj/src/java/org/apache/solr/client/solrj/request/schema/AbstractSchemaRequest.java
@@ -30,7 +30,7 @@ public abstract class AbstractSchemaRequest<T extends 
SolrResponse>
   }
 
   public AbstractSchemaRequest(METHOD m, String path, SolrParams params) {
-    super(m, path);
+    super(m, path, SolrRequestType.ADMIN);
     this.params = params != null ? params : new ModifiableSolrParams();
   }
 
@@ -38,9 +38,4 @@ public abstract class AbstractSchemaRequest<T extends 
SolrResponse>
   public SolrParams getParams() {
     return params;
   }
-
-  @Override
-  public String getRequestType() {
-    return SolrRequestType.ADMIN.toString();
-  }
 }
diff --git 
a/solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java 
b/solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java
index 1ba04ea2156..86ba3d4452d 100644
--- a/solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java
+++ b/solr/solrj/src/java/org/apache/solr/common/params/CommonParams.java
@@ -227,6 +227,7 @@ public interface CommonParams {
   String OK = "OK";
   String FAILURE = "FAILURE";
 
+  /** /admin paths which don't require a target collection */
   Set<String> ADMIN_PATHS =
       Set.of(
           CORES_HANDLER_PATH,
@@ -239,6 +240,7 @@ public interface CommonParams {
           AUTHC_PATH,
           AUTHZ_PATH,
           METRICS_PATH);
+
   String APISPEC_LOCATION = "apispec/";
   String INTROSPECT = "/_introspect";
 
diff --git a/solr/solrj/src/resources/java-template/api.mustache 
b/solr/solrj/src/resources/java-template/api.mustache
index 2239f9f9507..c374e2d879d 100644
--- a/solr/solrj/src/resources/java-template/api.mustache
+++ b/solr/solrj/src/resources/java-template/api.mustache
@@ -118,10 +118,12 @@ public class {{classname}} {
              {{/requiredParams}}
              */
             public 
{{operationIdCamelCase}}({{#allParams}}{{#required}}{{^isBodyParam}}{{^-first}},
 {{/-first}}{{{dataType}}} 
{{paramName}}{{/isBodyParam}}{{#isBodyParam}}{{#vendorExtensions.x-genericEntity}}{{^-first}},
 {{/-first}}{{{dataType}}} 
requestBody{{/vendorExtensions.x-genericEntity}}{{/isBodyParam}}{{/required}}{{/allParams}})
 {
+                // TODO Hardcode request type for now, but in reality we'll 
want to parse this out of the Operation data somehow
                 super(
                   SolrRequest.METHOD.valueOf("{{httpMethod}}"),
                   "{{{path}}}"{{#pathParams}}
-                    .replace("{" + "{{baseName}}" + "}", 
{{paramName}}{{^isString}}.toString(){{/isString}}){{/pathParams}}
+                    .replace("{" + "{{baseName}}" + "}", 
{{paramName}}{{^isString}}.toString(){{/isString}}){{/pathParams}},
+                    SolrRequestType.ADMIN
                 );
 
                 {{#requiredParams}}
@@ -223,12 +225,6 @@ public class {{classname}} {
             }
             {{/bodyParam}}
 
-            // TODO Hardcode this for now, but in reality we'll want to parse 
this out of the Operation data somehow
-            @Override
-            public String getRequestType() {
-              return SolrRequestType.ADMIN.toString();
-            }
-
             @Override
             public ApiVersion getApiVersion() {
               return ApiVersion.V2;
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 0b610339687..2fc66ad7913 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
@@ -439,6 +439,7 @@ public abstract class SolrExampleTests extends 
SolrExampleTestsBase {
       try (SolrClient adminClient = getHttpSolrClient(url)) {
         SolrQuery q = new SolrQuery();
         q.set("qt", "/admin/info/system");
+
         QueryResponse rsp = adminClient.query(q);
         assertNotNull(rsp.getResponse().get("mode"));
         assertNotNull(rsp.getResponse().get("lucene"));
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientRetryTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientRetryTest.java
index 505210c94df..61287300d2e 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientRetryTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientRetryTest.java
@@ -19,9 +19,10 @@ package org.apache.solr.client.solrj.impl;
 
 import java.util.Collections;
 import java.util.Optional;
-import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.cloud.SolrCloudTestCase;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.CommonParams;
@@ -60,14 +61,17 @@ public class CloudHttp2SolrClientRetryTest extends 
SolrCloudTestCase {
       solrClient.add(collectionName, new SolrInputDocument("id", "1"));
 
       ModifiableSolrParams params = new ModifiableSolrParams();
-      params.set(CommonParams.QT, "/admin/metrics");
       String updateRequestCountKey =
           
"solr.core.testRetry.shard1.replica_n1:UPDATE./update.requestTimes:count";
       params.set("key", updateRequestCountKey);
       params.set("indent", "true");
+      params.set(CommonParams.WT, "xml");
 
-      QueryResponse response = solrClient.query(collectionName, params, 
SolrRequest.METHOD.GET);
-      NamedList<Object> namedList = response.getResponse();
+      var metricsRequest =
+          new GenericSolrRequest(METHOD.GET, "/admin/metrics", 
SolrRequestType.ADMIN, params);
+      metricsRequest.setRequiresCollection(false);
+
+      NamedList<Object> namedList = solrClient.request(metricsRequest);
       System.out.println(namedList);
       NamedList<?> metrics = (NamedList<?>) namedList.get("metrics");
       assertEquals(1L, metrics.get(updateRequestCountKey));
@@ -84,8 +88,7 @@ public class CloudHttp2SolrClientRetryTest extends 
SolrCloudTestCase {
         TestInjection.reset();
       }
 
-      response = solrClient.query(collectionName, params, 
SolrRequest.METHOD.GET);
-      namedList = response.getResponse();
+      namedList = solrClient.request(metricsRequest);
       System.out.println(namedList);
       metrics = (NamedList<?>) namedList.get("metrics");
       assertEquals(2L, metrics.get(updateRequestCountKey));
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
index e8233413be1..717b90dcb6a 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudHttp2SolrClientTest.java
@@ -39,9 +39,12 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.lucene.tests.util.TestUtil;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.QueryResponse;
@@ -730,11 +733,13 @@ public class CloudHttp2SolrClientTest extends 
SolrCloudTestCase {
           }
 
           ModifiableSolrParams params = new ModifiableSolrParams();
-          params.set("qt", adminPath);
           params.set("action", "foobar"); // this should cause an error
-          QueryRequest req = new QueryRequest(params);
+          params.set("qt", adminPath);
+
+          var request =
+              new GenericSolrRequest(METHOD.GET, adminPath, 
SolrRequestType.ADMIN, params);
           try {
-            NamedList<Object> resp = client.request(req);
+            NamedList<Object> resp = client.request(request);
             fail("call to foo for admin path " + adminPath + " should have 
failed");
           } catch (Exception e) {
             // expected
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientRetryTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientRetryTest.java
index 9f4fbb85b61..92be2220c3d 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientRetryTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/CloudSolrClientRetryTest.java
@@ -17,9 +17,10 @@
 
 package org.apache.solr.client.solrj.impl;
 
-import org.apache.solr.client.solrj.SolrRequest;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.client.solrj.response.QueryResponse;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.cloud.SolrCloudTestCase;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.params.CommonParams;
@@ -55,14 +56,16 @@ public class CloudSolrClientRetryTest extends 
SolrCloudTestCase {
     solrClient.add(collectionName, new SolrInputDocument("id", "1"));
 
     ModifiableSolrParams params = new ModifiableSolrParams();
-    params.set(CommonParams.QT, "/admin/metrics");
     String updateRequestCountKey =
         
"solr.core.testRetry.shard1.replica_n1:UPDATE./update.requestTimes:count";
     params.set("key", updateRequestCountKey);
     params.set("indent", "true");
+    params.set(CommonParams.WT, "xml");
 
-    QueryResponse response = solrClient.query(collectionName, params, 
SolrRequest.METHOD.GET);
-    NamedList<Object> namedList = response.getResponse();
+    var metricsRequest =
+        new GenericSolrRequest(METHOD.GET, "/admin/metrics", 
SolrRequestType.ADMIN, params);
+
+    NamedList<Object> namedList = solrClient.request(metricsRequest);
     System.out.println(namedList);
     @SuppressWarnings({"rawtypes"})
     NamedList metrics = (NamedList) namedList.get("metrics");
@@ -80,8 +83,7 @@ public class CloudSolrClientRetryTest extends 
SolrCloudTestCase {
       TestInjection.reset();
     }
 
-    response = solrClient.query(collectionName, params, 
SolrRequest.METHOD.GET);
-    namedList = response.getResponse();
+    namedList = solrClient.request(metricsRequest);
     System.out.println(namedList);
     metrics = (NamedList) namedList.get("metrics");
     assertEquals(2L, metrics.get(updateRequestCountKey));
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 cb1b015d7e9..ae5beaaa209 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
@@ -39,9 +39,12 @@ import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.lucene.tests.util.TestUtil;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.request.V2Request;
@@ -666,11 +669,12 @@ public class CloudSolrClientTest extends 
SolrCloudTestCase {
           }
 
           ModifiableSolrParams params = new ModifiableSolrParams();
-          params.set("qt", adminPath);
           params.set("action", "foobar"); // this should cause an error
-          QueryRequest req = new QueryRequest(params);
+
+          var request =
+              new GenericSolrRequest(METHOD.GET, adminPath, 
SolrRequestType.ADMIN, params);
           try {
-            NamedList<Object> resp = client.request(req);
+            NamedList<Object> resp = client.request(request);
             fail("call to foo for admin path " + adminPath + " should have 
failed");
           } catch (Exception e) {
             // expected
diff --git 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SendUpdatesToLeadersOverrideTest.java
 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SendUpdatesToLeadersOverrideTest.java
index 91ad98170f1..89c674b01ee 100644
--- 
a/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SendUpdatesToLeadersOverrideTest.java
+++ 
b/solr/solrj/src/test/org/apache/solr/client/solrj/impl/SendUpdatesToLeadersOverrideTest.java
@@ -34,7 +34,6 @@ import java.util.stream.Collectors;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
-import org.apache.solr.client.solrj.request.IsUpdateRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.cloud.SolrCloudTestCase;
 import org.apache.solr.common.cloud.Replica;
@@ -48,7 +47,7 @@ import org.slf4j.LoggerFactory;
 
 /**
  * Test the behavior of {@link CloudSolrClient#isUpdatesToLeaders} and {@link
- * IsUpdateRequest#isSendToLeaders}.
+ * UpdateRequest#isSendToLeaders}.
  *
  * <p>This class uses {@link TrackingUpdateProcessorFactory} instances 
(configured both before, and
  * after the <code>distrib</code> processor) to inspect which replicas receive 
various {@link
@@ -202,7 +201,7 @@ public class SendUpdatesToLeadersOverrideTest extends 
SolrCloudTestCase {
    * setting <code>shards.preference=replica.type:PULL</code> on the input 
req, and then returning
    * that req
    */
-  private static AbstractUpdateRequest prefPull(final AbstractUpdateRequest 
req) {
+  private static UpdateRequest prefPull(final UpdateRequest req) {
     req.setParam("shards.preference", "replica.type:PULL");
     return req;
   }
@@ -481,7 +480,7 @@ public class SendUpdatesToLeadersOverrideTest extends 
SolrCloudTestCase {
   }
 
   /**
-   * Given a SolrClient, sends various updates were {@link 
IsUpdateRequest#isSendToLeaders} returns
+   * Given a SolrClient, sends various updates were {@link 
UpdateRequest#isSendToLeaders} returns
    * false, and asserts expectations that requests using {@link #prefPull} are 
all sent to PULL
    * replicas, regardless of how the client is configured.
    */
diff --git 
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractBasicDistributedZkTestBase.java
 
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractBasicDistributedZkTestBase.java
index ed37dcde551..de63551d4aa 100644
--- 
a/solr/test-framework/src/java/org/apache/solr/cloud/AbstractBasicDistributedZkTestBase.java
+++ 
b/solr/test-framework/src/java/org/apache/solr/cloud/AbstractBasicDistributedZkTestBase.java
@@ -41,12 +41,15 @@ import org.apache.lucene.util.IOUtils;
 import org.apache.solr.JSONTestUtil;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.AbstractUpdateRequest;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.Create;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.Unload;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.request.QueryRequest;
 import org.apache.solr.client.solrj.request.StreamingUpdateRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
@@ -1282,11 +1285,10 @@ public abstract class 
AbstractBasicDistributedZkTestBase extends AbstractFullDis
       ModifiableSolrParams params = new ModifiableSolrParams();
       // params.set("qt", 
"/admin/metrics?prefix=UPDATE.updateHandler&registry=solr.core." +
       // collection);
-      params.set("qt", "/admin/metrics");
       params.set("prefix", "UPDATE.updateHandler");
       params.set("registry", "solr.core." + collection);
       // use generic request to avoid extra processing of queries
-      QueryRequest req = new QueryRequest(params);
+      var req = new GenericSolrRequest(METHOD.GET, "/admin/metrics", 
SolrRequestType.ADMIN, params);
       NamedList<Object> resp = client.request(req);
       NamedList<?> metrics = (NamedList<?>) resp.get("metrics");
       NamedList<?> uhandlerCat = (NamedList<?>) metrics.getVal(0);
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 00a74dc7eb2..767847ff701 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
@@ -49,13 +49,15 @@ import java.util.function.Consumer;
 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.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.cloud.SocketProxy;
 import org.apache.solr.client.solrj.impl.CloudSolrClient;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
 import org.apache.solr.client.solrj.response.CoreAdminResponse;
@@ -2066,8 +2068,8 @@ public abstract class AbstractFullDistribZkTestBase 
extends AbstractDistribZkTes
     }
     params.set("name", collectionName);
     @SuppressWarnings({"rawtypes"})
-    SolrRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    SolrRequest request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
     CollectionAdminResponse res = new CollectionAdminResponse();
     if (client == null) {
@@ -2542,7 +2544,8 @@ public abstract class AbstractFullDistribZkTestBase 
extends AbstractDistribZkTes
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set("action", 
CollectionParams.CollectionAction.RELOAD.toString());
       params.set("name", testCollectionName);
-      QueryRequest request = new QueryRequest(params);
+      var request =
+          new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
       request.setPath("/admin/collections");
       client.request(request);
       Thread.sleep(2000); // reload can take a short while
diff --git 
a/solr/test-framework/src/java/org/apache/solr/cloud/ConfigRequest.java 
b/solr/test-framework/src/java/org/apache/solr/cloud/ConfigRequest.java
index 5f1d4912509..366b739f305 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/ConfigRequest.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/ConfigRequest.java
@@ -35,7 +35,7 @@ public class ConfigRequest extends 
CollectionRequiringSolrRequest<SolrResponse>
   protected final String message;
 
   public ConfigRequest(String message) {
-    super(SolrRequest.METHOD.POST, "/config");
+    super(SolrRequest.METHOD.POST, "/config", SolrRequestType.ADMIN);
     this.message = message;
   }
 
@@ -55,9 +55,4 @@ public class ConfigRequest extends 
CollectionRequiringSolrRequest<SolrResponse>
   public SolrResponse createResponse(NamedList<Object> client) {
     return new SolrResponseBase();
   }
-
-  @Override
-  public String getRequestType() {
-    return SolrRequest.SolrRequestType.ADMIN.toString();
-  }
 }
diff --git 
a/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCollectionsAPIDistributedZkTestBase.java
 
b/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCollectionsAPIDistributedZkTestBase.java
index fd984b244f5..d23b401a520 100644
--- 
a/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCollectionsAPIDistributedZkTestBase.java
+++ 
b/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractCollectionsAPIDistributedZkTestBase.java
@@ -42,10 +42,12 @@ import org.apache.lucene.tests.util.TestUtil;
 import org.apache.solr.client.api.model.CoreStatusResponse;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrQuery;
+import org.apache.solr.client.solrj.SolrRequest.METHOD;
+import org.apache.solr.client.solrj.SolrRequest.SolrRequestType;
 import org.apache.solr.client.solrj.SolrServerException;
 import org.apache.solr.client.solrj.request.CollectionAdminRequest;
 import org.apache.solr.client.solrj.request.CoreAdminRequest;
-import org.apache.solr.client.solrj.request.QueryRequest;
+import org.apache.solr.client.solrj.request.GenericSolrRequest;
 import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.CollectionAdminResponse;
 import org.apache.solr.client.solrj.response.CoreAdminResponse;
@@ -191,8 +193,8 @@ public abstract class 
AbstractCollectionsAPIDistributedZkTestBase extends SolrCl
     String collectionName = "badactioncollection";
     params.set("name", collectionName);
     params.set("numShards", 2);
-    final QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
     expectThrows(
         Exception.class,
@@ -207,8 +209,8 @@ public abstract class 
AbstractCollectionsAPIDistributedZkTestBase extends SolrCl
     params.set("action", CollectionAction.CREATE.toString());
     params.set("numShards", 2);
     // missing required collection parameter
-    final QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
     expectThrows(
         Exception.class,
@@ -226,8 +228,8 @@ public abstract class 
AbstractCollectionsAPIDistributedZkTestBase extends SolrCl
     params.set(REPLICATION_FACTOR, 10);
     params.set("collection.configName", "conf");
 
-    final QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
 
     expectThrows(
         Exception.class,
@@ -245,8 +247,8 @@ public abstract class 
AbstractCollectionsAPIDistributedZkTestBase extends SolrCl
     params.set("numShards", 0);
     params.set("collection.configName", "conf");
 
-    final QueryRequest request = new QueryRequest(params);
-    request.setPath("/admin/collections");
+    var request =
+        new GenericSolrRequest(METHOD.GET, "/admin/collections", 
SolrRequestType.ADMIN, params);
     expectThrows(
         Exception.class,
         () -> {
@@ -673,8 +675,9 @@ public abstract class 
AbstractCollectionsAPIDistributedZkTestBase extends SolrCl
               params.set("collection", collectionName);
               params.set("shard", "shard1");
               params.set("name", coreName);
-              QueryRequest request = new QueryRequest(params);
-              request.setPath("/admin/collections");
+              var request =
+                  new GenericSolrRequest(
+                      METHOD.GET, "/admin/collections", SolrRequestType.ADMIN, 
params);
               cluster.getSolrClient().request(request);
             });
 

Reply via email to