You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ds...@apache.org on 2026/07/28 14:13:53 UTC

(solr) branch branch_10x updated (fe5dedbc989 -> e76c7588624)

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

dsmiley pushed a change to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/solr.git


    from fe5dedbc989 Improve writeChangelog gradle task (#4007)
     new 1172e9a7c77 Java cleanups in o.a.s.cluster.events files (#4554)
     new 1ec24a1c968 SOLR-18310: opentelemetry: switch default from gRPC to http/protobuf(#4646)
     new 60e1da7f9c0 packaging: Remove docs/ from the Solr binary distribution (#4641)
     new 00d1dcc10a6 this is a additive feature that users opt into (#4670)
     new 7e636dc2c10 SOLR-18248 : Migration of Tasks V2 APIs to JAX-RS Constructs (#4452)
     new e76c7588624 Remove dead classes BaseHandlerApiSupport and PrintWriterWrapper (#4654)

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../PR#4629-envutils-core-properties.yml           |   2 +-
 .../unreleased/PR#4641-remove_docs_distro.yml      |   8 +
 changelog/unreleased/SOLR-18248-list-tasks.yml     |   8 +
 .../unreleased/SOLR-18310-otel-jdk-sender.yml      |   9 +
 dev-tools/scripts/smokeTestRelease.py              |   4 +-
 gradle/documentation/documentation.gradle          |  53 +----
 gradle/documentation/markdown.gradle               |   9 -
 gradle/libs.versions.toml                          |   1 +
 .../{ListAliasesApi.java => TasksApi.java}         |  33 +--
 ...iqueRequestBody.java => ActiveTaskDetails.java} |  15 +-
 ...dsResponse.java => ListActiveTaskResponse.java} |   6 +-
 ...UnusedResponse.java => TaskStatusResponse.java} |  22 +-
 .../apache/solr/cluster/events/ClusterEvent.java   |   4 +-
 .../cluster/events/ClusterEventProducerBase.java   |   4 +-
 .../events/impl/ClusterEventProducerFactory.java   |   9 +-
 .../impl/CollectionsRepairEventListener.java       |   8 +-
 .../impl/DelegatingClusterEventProducer.java       |   2 +-
 .../solr/cluster/placement/AttributeFetcher.java   |   2 +-
 .../solr/cluster/placement/BalanceRequest.java     |   2 -
 .../solr/cluster/placement/CollectionMetrics.java  |   2 +-
 .../org/apache/solr/cluster/placement/Metric.java  |   2 +-
 .../solr/cluster/placement/PlacementContext.java   |   2 +-
 .../solr/cluster/placement/PlacementException.java |   5 -
 .../placement/PlacementModificationException.java  |   8 -
 .../solr/cluster/placement/PlacementPlugin.java    |   2 +-
 .../solr/cluster/placement/ShardMetrics.java       |   2 +-
 .../placement/impl/AttributeFetcherImpl.java       |   5 +-
 .../cluster/placement/impl/BalanceRequestImpl.java |   5 -
 .../solr/cluster/placement/impl/MetricImpl.java    |   6 +-
 .../placement/impl/ModificationRequestImpl.java    |  30 ---
 .../cluster/placement/impl/NodeMetricImpl.java     |   9 -
 .../impl/PlacementPluginAssignStrategy.java        |   7 +-
 .../impl/PlacementPluginFactoryLoader.java         |  28 ++-
 .../impl/SimpleClusterAbstractionsImpl.java        |  69 ++----
 .../placement/plugins/AffinityPlacementConfig.java |   5 +-
 .../solr/handler/admin/BaseHandlerApiSupport.java  | 236 ---------------------
 .../solr/handler/admin/HealthCheckHandler.java     |   3 -
 .../apache/solr/handler/admin/api/ActiveTask.java  |  85 ++++++++
 .../solr/handler/admin/api/ListActiveTasksAPI.java |  48 -----
 .../handler/component/ActiveTaskQuerySupport.java  | 165 ++++++++++++++
 .../component/ActiveTasksListComponent.java        | 128 -----------
 .../handler/component/ActiveTasksListHandler.java  |  64 +++---
 .../handler/component/TaskManagementHandler.java   |   3 -
 .../solr/metrics/otel/MetricExporterFactory.java   |   2 +-
 .../apache/solr/security/PrintWriterWrapper.java   | 211 ------------------
 .../solr/handler/admin/api/ActiveTaskTest.java     | 100 +++++++++
 .../org/apache/solr/search/TestTaskManagement.java | 116 ++++++++++
 solr/cross-dc-manager/gradle.lockfile              |  25 +--
 .../src/markdown/online-link.template.md           |  21 --
 solr/licenses/grpc-netty-1.82.0.jar.sha1           |   1 -
 .../netty-codec-http2-4.2.15.Final.jar.sha1        |   1 -
 .../netty-codec-socks-4.2.15.Final.jar.sha1        |   1 -
 .../netty-handler-proxy-4.2.15.Final.jar.sha1      |   1 -
 ...entelemetry-exporter-sender-jdk-1.56.0.jar.sha1 |   1 +
 ...elemetry-exporter-sender-okhttp-1.56.0.jar.sha1 |   1 -
 .../proto-google-common-protos-2.64.1.jar.sha1     |   1 -
 solr/modules/opentelemetry/build.gradle            |  16 +-
 solr/modules/opentelemetry/gradle.lockfile         |  28 +--
 .../solr/opentelemetry/OtelTracerConfigurator.java |   2 +-
 solr/packaging/README.txt                          |  11 +-
 solr/packaging/build.gradle                        |  16 +-
 solr/server/etc/security.policy                    |   3 +
 .../pages/distributed-tracing.adoc                 |  23 +-
 .../deployment-guide/pages/metrics-reporting.adoc  |   6 +-
 .../deployment-guide/pages/task-management.adoc    |  62 +++++-
 .../pages/major-changes-in-solr-10.adoc            |   8 +
 66 files changed, 755 insertions(+), 1022 deletions(-)
 create mode 100644 changelog/unreleased/PR#4641-remove_docs_distro.yml
 create mode 100644 changelog/unreleased/SOLR-18248-list-tasks.yml
 create mode 100644 changelog/unreleased/SOLR-18310-otel-jdk-sender.yml
 copy solr/api/src/java/org/apache/solr/client/api/endpoint/{ListAliasesApi.java => TasksApi.java} (58%)
 copy solr/api/src/java/org/apache/solr/client/api/model/{BalanceShardUniqueRequestBody.java => ActiveTaskDetails.java} (79%)
 copy solr/api/src/java/org/apache/solr/client/api/model/{SchemaListFieldsResponse.java => ListActiveTaskResponse.java} (88%)
 copy solr/api/src/java/org/apache/solr/client/api/model/{PurgeUnusedResponse.java => TaskStatusResponse.java} (72%)
 delete mode 100644 solr/core/src/java/org/apache/solr/handler/admin/BaseHandlerApiSupport.java
 create mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java
 delete mode 100644 solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasksAPI.java
 create mode 100644 solr/core/src/java/org/apache/solr/handler/component/ActiveTaskQuerySupport.java
 delete mode 100644 solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListComponent.java
 delete mode 100644 solr/core/src/java/org/apache/solr/security/PrintWriterWrapper.java
 create mode 100644 solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.java
 delete mode 100644 solr/documentation/src/markdown/online-link.template.md
 delete mode 100644 solr/licenses/grpc-netty-1.82.0.jar.sha1
 delete mode 100644 solr/licenses/netty-codec-http2-4.2.15.Final.jar.sha1
 delete mode 100644 solr/licenses/netty-codec-socks-4.2.15.Final.jar.sha1
 delete mode 100644 solr/licenses/netty-handler-proxy-4.2.15.Final.jar.sha1
 create mode 100644 solr/licenses/opentelemetry-exporter-sender-jdk-1.56.0.jar.sha1
 delete mode 100644 solr/licenses/opentelemetry-exporter-sender-okhttp-1.56.0.jar.sha1
 delete mode 100644 solr/licenses/proto-google-common-protos-2.64.1.jar.sha1


(solr) 04/06: this is a additive feature that users opt into (#4670)

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 00d1dcc10a6e7d3df5a073fbf632173f29cf7b92
Author: Eric Pugh <ep...@opensourceconnections.com>
AuthorDate: Sun Jul 26 08:18:14 2026 -0400

    this is a additive feature that users opt into (#4670)
    
    (cherry picked from commit f27d8f0e533194dcccb053baccdec18a2d3ca887)
---
 changelog/unreleased/PR#4629-envutils-core-properties.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/changelog/unreleased/PR#4629-envutils-core-properties.yml b/changelog/unreleased/PR#4629-envutils-core-properties.yml
index f700119fe1b..4959786b9ef 100644
--- a/changelog/unreleased/PR#4629-envutils-core-properties.yml
+++ b/changelog/unreleased/PR#4629-envutils-core-properties.yml
@@ -1,5 +1,5 @@
 title: Core system properties can now also be configured via environment variables
-type: changed
+type: added
 authors:
   - name: Prithvi S
 links:


(solr) 01/06: Java cleanups in o.a.s.cluster.events files (#4554)

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 1172e9a7c776d0bacee3653ce879deafe10c631d
Author: Eric Pugh <ep...@opensourceconnections.com>
AuthorDate: Wed Jul 22 12:35:19 2026 -0400

    Java cleanups in o.a.s.cluster.events files (#4554)
    
    (cherry picked from commit 5566b8bd3b45969eafaa7b4304fe8cfa87907b38)
---
 .../apache/solr/cluster/events/ClusterEvent.java   |  4 +-
 .../cluster/events/ClusterEventProducerBase.java   |  4 +-
 .../events/impl/ClusterEventProducerFactory.java   |  9 ++-
 .../impl/CollectionsRepairEventListener.java       |  8 +--
 .../impl/DelegatingClusterEventProducer.java       |  2 +-
 .../solr/cluster/placement/AttributeFetcher.java   |  2 +-
 .../solr/cluster/placement/BalanceRequest.java     |  2 -
 .../solr/cluster/placement/CollectionMetrics.java  |  2 +-
 .../org/apache/solr/cluster/placement/Metric.java  |  2 +-
 .../solr/cluster/placement/PlacementContext.java   |  2 +-
 .../solr/cluster/placement/PlacementException.java |  5 --
 .../placement/PlacementModificationException.java  |  8 ---
 .../solr/cluster/placement/PlacementPlugin.java    |  2 +-
 .../solr/cluster/placement/ShardMetrics.java       |  2 +-
 .../placement/impl/AttributeFetcherImpl.java       |  5 +-
 .../cluster/placement/impl/BalanceRequestImpl.java |  5 --
 .../solr/cluster/placement/impl/MetricImpl.java    |  6 +-
 .../placement/impl/ModificationRequestImpl.java    | 30 ----------
 .../cluster/placement/impl/NodeMetricImpl.java     |  9 ---
 .../impl/PlacementPluginAssignStrategy.java        |  7 +--
 .../impl/PlacementPluginFactoryLoader.java         | 28 ++++-----
 .../impl/SimpleClusterAbstractionsImpl.java        | 69 ++++++++--------------
 .../placement/plugins/AffinityPlacementConfig.java |  5 +-
 23 files changed, 59 insertions(+), 159 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/cluster/events/ClusterEvent.java b/solr/core/src/java/org/apache/solr/cluster/events/ClusterEvent.java
index f2fb184fb07..c800ce8b6f0 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/ClusterEvent.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/ClusterEvent.java
@@ -32,8 +32,8 @@ public interface ClusterEvent {
     COLLECTIONS_REMOVED,
     /** Cluster properties have changed. */
     CLUSTER_PROPERTIES_CHANGED
-    // other types? eg. Overseer leader change, shard leader change,
-    // node overload (eg. CPU / MEM circuit breakers tripped)?
+    // other types? e.g. Overseer leader change, shard leader change,
+    // node overload (e.g. CPU / MEM circuit breakers tripped)?
   }
 
   /** Get event type. */
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/ClusterEventProducerBase.java b/solr/core/src/java/org/apache/solr/cluster/events/ClusterEventProducerBase.java
index ee16baf41fe..376d331c07d 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/ClusterEventProducerBase.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/ClusterEventProducerBase.java
@@ -84,9 +84,7 @@ public abstract class ClusterEventProducerBase implements ClusterEventProducer {
   @Override
   public void close() throws IOException {
     synchronized (listeners) {
-      listeners
-          .values()
-          .forEach(listenerSet -> listenerSet.forEach(listener -> IOUtils.closeQuietly(listener)));
+      listeners.values().forEach(listenerSet -> listenerSet.forEach(IOUtils::closeQuietly));
     }
   }
 
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerFactory.java b/solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerFactory.java
index e7401940ad7..e7f57cbcca9 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerFactory.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/impl/ClusterEventProducerFactory.java
@@ -93,13 +93,13 @@ public class ClusterEventProducerFactory extends ClusterEventProducerBase {
   /**
    * Create a {@link ClusterEventProducer} based on the current plugin configurations.
    *
-   * <p>NOTE: this method can only be called once because it has side-effects, such as transferring
+   * <p>NOTE: this method can only be called once because it has side effects, such as transferring
    * the initially collected listeners to the resulting producer's instance, and installing a {@link
    * org.apache.solr.api.ContainerPluginsRegistry.PluginRegistryListener}. Calling this method more
    * than once will result in an exception.
    *
    * @param plugins current plugin configurations
-   * @return configured instance of cluster event producer (with side-effects, see above)
+   * @return configured instance of cluster event producer (with side effects, see above)
    */
   public DelegatingClusterEventProducer create(ContainerPluginsRegistry plugins) {
     if (created) {
@@ -201,9 +201,8 @@ public class ClusterEventProducerFactory extends ClusterEventProducerBase {
       plugins.unregisterListener(initialPluginListener);
       // transfer listeners that are already registered
       listeners.forEach(
-          (type, listenersSet) -> {
-            listenersSet.forEach(listener -> target.registerListener(listener, type));
-          });
+          (type, listenersSet) ->
+              listenersSet.forEach(listener -> target.registerListener(listener, type)));
       listeners.clear();
     }
   }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java b/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
index 0d8c26d6c06..134e3d075e7 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/impl/CollectionsRepairEventListener.java
@@ -195,10 +195,7 @@ public class CollectionsRepairEventListener
                         newPositions.put(coll.getName(), positions);
                       } catch (Exception e) {
                         log.warn(
-                            "Exception computing positions for {}/{}: {}",
-                            coll.getName(),
-                            shard,
-                            e);
+                            "Exception computing positions for {}/{}", coll.getName(), shard, e);
                       }
                     });
               });
@@ -229,8 +226,7 @@ public class CollectionsRepairEventListener
           try {
             solrClient.request(addReplica);
           } catch (Exception e) {
-            log.warn(
-                "Exception calling ADDREPLICA {}: {}", addReplica.getParams().toQueryString(), e);
+            log.warn("Exception calling ADDREPLICA {}", addReplica.getParams().toQueryString(), e);
           }
         });
   }
diff --git a/solr/core/src/java/org/apache/solr/cluster/events/impl/DelegatingClusterEventProducer.java b/solr/core/src/java/org/apache/solr/cluster/events/impl/DelegatingClusterEventProducer.java
index 551b9bfd397..61fffdf5c98 100644
--- a/solr/core/src/java/org/apache/solr/cluster/events/impl/DelegatingClusterEventProducer.java
+++ b/solr/core/src/java/org/apache/solr/cluster/events/impl/DelegatingClusterEventProducer.java
@@ -96,7 +96,7 @@ public final class DelegatingClusterEventProducer extends ClusterEventProducerBa
           log.debug("--- started delegate {}", delegate);
         }
       } catch (Exception e) {
-        log.warn("Unable to start the new delegate {}: {}", delegate.getClass().getName(), e);
+        log.warn("Unable to start the new delegate {}", delegate.getClass().getName(), e);
       }
     } else {
       if (log.isDebugEnabled()) {
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/AttributeFetcher.java b/solr/core/src/java/org/apache/solr/cluster/placement/AttributeFetcher.java
index a751d4bc08d..09186a0afa6 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/AttributeFetcher.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/AttributeFetcher.java
@@ -65,7 +65,7 @@ public interface AttributeFetcher {
   /**
    * Fetches all requested node attributes from all nodes passed to {@link #fetchFrom(Set)} as well
    * as non-node attributes (those requested using e.g. {@link
-   * #requestCollectionMetrics(SolrCollection, Set)}.
+   * #requestCollectionMetrics(SolrCollection, Set)}).
    *
    * @return An instance allowing retrieval of all attributes that could be fetched.
    */
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/BalanceRequest.java b/solr/core/src/java/org/apache/solr/cluster/placement/BalanceRequest.java
index f967b7fa808..9dfb0ee56e1 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/BalanceRequest.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/BalanceRequest.java
@@ -43,6 +43,4 @@ public interface BalanceRequest extends ModificationRequest {
    *     the error itself rather than calling the plugin).
    */
   Set<Node> getNodes();
-
-  int getMaximumBalanceSkew();
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/CollectionMetrics.java b/solr/core/src/java/org/apache/solr/cluster/placement/CollectionMetrics.java
index c6afc8b480d..d0a8681ccd5 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/CollectionMetrics.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/CollectionMetrics.java
@@ -21,7 +21,7 @@ import java.util.Iterator;
 import java.util.Optional;
 
 /**
- * Collection-level metrics. Currently this class is a container just for shard-level metrics but
+ * Collection-level metrics. Currently, this class is a container just for shard-level metrics but
  * future versions may add other primitive collection-level metrics.
  */
 public interface CollectionMetrics {
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/Metric.java b/solr/core/src/java/org/apache/solr/cluster/placement/Metric.java
index afa1040b96a..5ddd0d0d456 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/Metric.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/Metric.java
@@ -23,7 +23,7 @@ package org.apache.solr.cluster.placement;
  */
 public interface Metric<T> {
 
-  /** Return the short-hand name that identifies this attribute. */
+  /** Return the shorthand name that identifies this attribute. */
   String getName();
 
   /** Return the internal name of a Solr metric associated with this attribute. */
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/PlacementContext.java b/solr/core/src/java/org/apache/solr/cluster/placement/PlacementContext.java
index be7b0282a79..ae161610e60 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/PlacementContext.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/PlacementContext.java
@@ -33,7 +33,7 @@ public interface PlacementContext {
 
   /**
    * Factory used by the plugin to fetch additional attributes from the cluster nodes, such as count
-   * of cores, system properties etc..
+   * of cores, system properties etc.
    */
   AttributeFetcher getAttributeFetcher();
 
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/PlacementException.java b/solr/core/src/java/org/apache/solr/cluster/placement/PlacementException.java
index bbe49f62746..c50b667ee52 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/PlacementException.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/PlacementException.java
@@ -39,9 +39,4 @@ public class PlacementException extends Exception {
   public PlacementException(Throwable cause) {
     super(cause);
   }
-
-  protected PlacementException(
-      String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
-    super(message, cause, enableSuppression, writableStackTrace);
-  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/PlacementModificationException.java b/solr/core/src/java/org/apache/solr/cluster/placement/PlacementModificationException.java
index 30439188a22..cd780d83bcf 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/PlacementModificationException.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/PlacementModificationException.java
@@ -27,10 +27,6 @@ import java.util.Map;
 public class PlacementModificationException extends PlacementException {
   private final Map<String, String> rejectedModifications = new HashMap<>();
 
-  public PlacementModificationException() {
-    super();
-  }
-
   public PlacementModificationException(String message) {
     super(message);
   }
@@ -39,10 +35,6 @@ public class PlacementModificationException extends PlacementException {
     super(message, cause);
   }
 
-  public PlacementModificationException(Throwable cause) {
-    super(cause);
-  }
-
   /**
    * Add information about the modification that cause this exception.
    *
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/PlacementPlugin.java b/solr/core/src/java/org/apache/solr/cluster/placement/PlacementPlugin.java
index d2924d344b8..6bc14205f2e 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/PlacementPlugin.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/PlacementPlugin.java
@@ -98,5 +98,5 @@ public interface PlacementPlugin {
    */
   default void verifyAllowedModification(
       ModificationRequest modificationRequest, PlacementContext placementContext)
-      throws PlacementException, InterruptedException {}
+      throws PlacementException {}
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/ShardMetrics.java b/solr/core/src/java/org/apache/solr/cluster/placement/ShardMetrics.java
index 0ca45267ff0..3be201f1d6f 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/ShardMetrics.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/ShardMetrics.java
@@ -20,7 +20,7 @@ import java.util.Iterator;
 import java.util.Optional;
 
 /**
- * Shard-level metrics. Currently this is just a container for replica-level metrics but future
+ * Shard-level metrics. Currently, this is just a container for replica-level metrics but future
  * versions may add other primitive shard-level metrics.
  */
 public interface ShardMetrics {
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/AttributeFetcherImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/AttributeFetcherImpl.java
index 2aa4203f91a..cca227000f7 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/AttributeFetcherImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/AttributeFetcherImpl.java
@@ -101,7 +101,7 @@ public class AttributeFetcherImpl implements AttributeFetcher {
     // In order to match the returned values for the various snitches, we need to keep track of
     // where each received value goes. Given the target maps are of different types (the maps from
     // Node to whatever defined above) we instead pass a function taking two arguments, the node and
-    // the (non null) returned value, that will cast the value into the appropriate type for the
+    // the (non-null) returned value, that will cast the value into the appropriate type for the
     // snitch tag and insert it into the appropriate map with the node as the key.
     for (String sysPropSnitch : requestedNodeSystemSnitchTags) {
       systemSnitchToNodeToValue.put(sysPropSnitch, new HashMap<>());
@@ -207,11 +207,10 @@ public class AttributeFetcherImpl implements AttributeFetcher {
       Map<String, Map<Node, String>> systemSnitchToNodeToValue,
       Map<NodeMetric<?>, Map<Node, Object>> metricSnitchToNodeToValue) {
 
-    Set<String> allRequestedTags = new HashSet<>();
     Map<String, NodeMetric<?>> tagToMetric = new HashMap<>();
 
     // Add system property tags we need to request
-    allRequestedTags.addAll(requestedNodeSystemSnitchTags);
+    Set<String> allRequestedTags = new HashSet<>(requestedNodeSystemSnitchTags);
 
     // Add metric tags we need to request
     for (NodeMetric<?> metric : requestedNodeMetricSnitchTags) {
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/BalanceRequestImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/BalanceRequestImpl.java
index 95454f9dbbe..4a2f39ba8eb 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/BalanceRequestImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/BalanceRequestImpl.java
@@ -45,11 +45,6 @@ public class BalanceRequestImpl implements BalanceRequest {
     return nodes;
   }
 
-  @Override
-  public int getMaximumBalanceSkew() {
-    return maximumBalanceSkew;
-  }
-
   @Override
   public SolrCollection getCollection() {
     return solrCollection;
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/MetricImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/MetricImpl.java
index b3c5782bd13..f6a64d8eb51 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/MetricImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/MetricImpl.java
@@ -68,7 +68,7 @@ public abstract class MetricImpl<T> implements Metric<T> {
   /**
    * Create a metric attribute.
    *
-   * @param name short-hand name that identifies this attribute.
+   * @param name shorthand name that identifies this attribute.
    * @param internalName internal name of a Solr metric.
    */
   public MetricImpl(String name, String internalName) {
@@ -78,7 +78,7 @@ public abstract class MetricImpl<T> implements Metric<T> {
   /**
    * Create a metric attribute.
    *
-   * @param name short-hand name that identifies this attribute.
+   * @param name shorthand name that identifies this attribute.
    * @param internalName internal name of a Solr metric.
    * @param converter optional raw value converter. If null then {@link #IDENTITY_CONVERTER} will be
    *     used.
@@ -90,7 +90,7 @@ public abstract class MetricImpl<T> implements Metric<T> {
   /**
    * Create a metric attribute with labels.
    *
-   * @param name short-hand name that identifies this attribute.
+   * @param name shorthand name that identifies this attribute.
    * @param internalName internal name of a Solr metric.
    * @param labelKey optional label key for Prometheus format labeled metrics.
    * @param labelValue optional label value for Prometheus format labeled metrics.
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/ModificationRequestImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/ModificationRequestImpl.java
index de542fcefe3..1532fc21e64 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/ModificationRequestImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/ModificationRequestImpl.java
@@ -24,9 +24,7 @@ import org.apache.solr.cluster.Shard;
 import org.apache.solr.cluster.SolrCollection;
 import org.apache.solr.cluster.placement.DeleteCollectionRequest;
 import org.apache.solr.cluster.placement.DeleteReplicasRequest;
-import org.apache.solr.cluster.placement.DeleteShardsRequest;
 import org.apache.solr.common.cloud.DocCollection;
-import org.apache.solr.common.cloud.Slice;
 
 /** Helper class to create modification request instances. */
 public class ModificationRequestImpl {
@@ -77,7 +75,6 @@ public class ModificationRequestImpl {
     SolrCollection solrCollection =
         SimpleClusterAbstractionsImpl.SolrCollectionImpl.fromDocCollection(docCollection);
     Shard shard = solrCollection.getShard(shardName);
-    Slice slice = docCollection.getSlice(shardName);
     Set<Replica> solrReplicas = new HashSet<>();
     replicas.forEach(
         replica -> {
@@ -85,31 +82,4 @@ public class ModificationRequestImpl {
         });
     return createDeleteReplicasRequest(solrCollection, solrReplicas);
   }
-
-  public static DeleteShardsRequest createDeleteShardsRequest(
-      SolrCollection collection, Set<String> shardNames) {
-    return new DeleteShardsRequest() {
-      @Override
-      public Set<String> getShardNames() {
-        return shardNames;
-      }
-
-      @Override
-      public SolrCollection getCollection() {
-        return collection;
-      }
-
-      @Override
-      public String toString() {
-        return "DeleteShardsRequest{collection=" + collection.getName() + ",shards=" + shardNames;
-      }
-    };
-  }
-
-  public static DeleteShardsRequest createDeleteShardsRequest(
-      DocCollection docCollection, Set<String> shardNames) {
-    SolrCollection solrCollection =
-        SimpleClusterAbstractionsImpl.SolrCollectionImpl.fromDocCollection(docCollection);
-    return createDeleteShardsRequest(solrCollection, shardNames);
-  }
 }
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
index 75fac2406d0..4f76896a320 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/NodeMetricImpl.java
@@ -56,15 +56,6 @@ public class NodeMetricImpl<T> extends MetricImpl<T> implements NodeMetric<T> {
     super(key, key, null, null, converter);
   }
 
-  public NodeMetricImpl(
-      String name,
-      String internalName,
-      String labelKey,
-      String labelValue,
-      Function<Object, T> converter) {
-    super(name, internalName, labelKey, labelValue, converter);
-  }
-
   public NodeMetricImpl(String key) {
     super(key, key);
   }
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginAssignStrategy.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginAssignStrategy.java
index f005dc24641..13e2a0b53a4 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginAssignStrategy.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginAssignStrategy.java
@@ -18,7 +18,6 @@
 package org.apache.solr.cluster.placement.impl;
 
 import java.io.IOException;
-import java.lang.invoke.MethodHandles;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
@@ -41,14 +40,10 @@ import org.apache.solr.common.cloud.Replica;
 import org.apache.solr.common.cloud.ReplicaPosition;
 import org.apache.solr.common.cloud.Slice;
 import org.apache.solr.common.util.CollectionUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /** This assign strategy delegates placement computation to "plugin" code. */
 public class PlacementPluginAssignStrategy implements Assign.AssignStrategy {
 
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
   private final PlacementPlugin plugin;
 
   public PlacementPluginAssignStrategy(PlacementPlugin plugin) {
@@ -127,7 +122,7 @@ public class PlacementPluginAssignStrategy implements Assign.AssignStrategy {
 
   private Replica findReplica(
       SolrCloudManager solrCloudManager, org.apache.solr.cluster.Replica replica) {
-    DocCollection collection = null;
+    DocCollection collection;
     try {
       collection =
           solrCloudManager
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginFactoryLoader.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginFactoryLoader.java
index 00ee44f67b3..b7f582d01f7 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginFactoryLoader.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/PlacementPluginFactoryLoader.java
@@ -109,22 +109,18 @@ public class PlacementPluginFactoryLoader {
           "Default replica placement plugin set in {} to {}",
           PLACEMENTPLUGIN_DEFAULT_SYSPROP,
           defaultPluginId);
-      switch (defaultPluginId.toLowerCase(Locale.ROOT)) {
-        case "simple":
-          return new SimplePlacementFactory();
-        case "affinity":
-          return new AffinityPlacementFactory();
-        case "minimizecores":
-          return new MinimizeCoresPlacementFactory();
-        case "random":
-          return new RandomPlacementFactory();
-        default:
-          throw new SolrException(
-              SolrException.ErrorCode.SERVER_ERROR,
-              "Invalid value for system property '"
-                  + PLACEMENTPLUGIN_DEFAULT_SYSPROP
-                  + "'. Supported values are 'simple', 'random', 'affinity' and 'minimizecores'");
-      }
+      return switch (defaultPluginId.toLowerCase(Locale.ROOT)) {
+        case "simple" -> new SimplePlacementFactory();
+        case "affinity" -> new AffinityPlacementFactory();
+        case "minimizecores" -> new MinimizeCoresPlacementFactory();
+        case "random" -> new RandomPlacementFactory();
+        default ->
+            throw new SolrException(
+                SolrException.ErrorCode.SERVER_ERROR,
+                "Invalid value for system property '"
+                    + PLACEMENTPLUGIN_DEFAULT_SYSPROP
+                    + "'. Supported values are 'simple', 'random', 'affinity' and 'minimizecores'");
+      };
     } else {
       // TODO: Consider making the ootb default AffinityPlacementFactory, see
       // https://issues.apache.org/jira/browse/SOLR-16492
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/impl/SimpleClusterAbstractionsImpl.java b/solr/core/src/java/org/apache/solr/cluster/placement/impl/SimpleClusterAbstractionsImpl.java
index d1b92ba2a4b..f8af1e41858 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/impl/SimpleClusterAbstractionsImpl.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/impl/SimpleClusterAbstractionsImpl.java
@@ -251,20 +251,13 @@ class SimpleClusterAbstractionsImpl {
     }
 
     private ShardState translateState(Slice.State state) {
-      switch (state) {
-        case ACTIVE:
-          return ShardState.ACTIVE;
-        case INACTIVE:
-          return ShardState.INACTIVE;
-        case CONSTRUCTION:
-          return ShardState.CONSTRUCTION;
-        case RECOVERY:
-          return ShardState.RECOVERY;
-        case RECOVERY_FAILED:
-          return ShardState.RECOVERY_FAILED;
-        default:
-          throw new RuntimeException("Unexpected " + state);
-      }
+      return switch (state) {
+        case ACTIVE -> ShardState.ACTIVE;
+        case INACTIVE -> ShardState.INACTIVE;
+        case CONSTRUCTION -> ShardState.CONSTRUCTION;
+        case RECOVERY -> ShardState.RECOVERY;
+        case RECOVERY_FAILED -> ShardState.RECOVERY_FAILED;
+      };
     }
 
     @Override
@@ -385,31 +378,20 @@ class SimpleClusterAbstractionsImpl {
     }
 
     private Replica.ReplicaType translateType(org.apache.solr.common.cloud.Replica.Type type) {
-      switch (type) {
-        case NRT:
-          return Replica.ReplicaType.NRT;
-        case TLOG:
-          return Replica.ReplicaType.TLOG;
-        case PULL:
-          return Replica.ReplicaType.PULL;
-        default:
-          throw new RuntimeException("Unexpected " + type);
-      }
+      return switch (type) {
+        case NRT -> ReplicaType.NRT;
+        case TLOG -> ReplicaType.TLOG;
+        case PULL -> ReplicaType.PULL;
+      };
     }
 
     private Replica.ReplicaState translateState(State state) {
-      switch (state) {
-        case ACTIVE:
-          return Replica.ReplicaState.ACTIVE;
-        case DOWN:
-          return Replica.ReplicaState.DOWN;
-        case RECOVERING:
-          return Replica.ReplicaState.RECOVERING;
-        case RECOVERY_FAILED:
-          return Replica.ReplicaState.RECOVERY_FAILED;
-        default:
-          throw new RuntimeException("Unexpected " + state);
-      }
+      return switch (state) {
+        case ACTIVE -> ReplicaState.ACTIVE;
+        case DOWN -> ReplicaState.DOWN;
+        case RECOVERING -> ReplicaState.RECOVERING;
+        case RECOVERY_FAILED -> ReplicaState.RECOVERY_FAILED;
+      };
     }
 
     @Override
@@ -449,16 +431,11 @@ class SimpleClusterAbstractionsImpl {
      * an internal SolrCloud implementation class to the plugin API.
      */
     static org.apache.solr.common.cloud.Replica.Type toCloudReplicaType(ReplicaType type) {
-      switch (type) {
-        case NRT:
-          return org.apache.solr.common.cloud.Replica.Type.NRT;
-        case TLOG:
-          return org.apache.solr.common.cloud.Replica.Type.TLOG;
-        case PULL:
-          return org.apache.solr.common.cloud.Replica.Type.PULL;
-        default:
-          throw new IllegalArgumentException("Unknown " + type);
-      }
+      return switch (type) {
+        case NRT -> org.apache.solr.common.cloud.Replica.Type.NRT;
+        case TLOG -> org.apache.solr.common.cloud.Replica.Type.TLOG;
+        case PULL -> org.apache.solr.common.cloud.Replica.Type.PULL;
+      };
     }
 
     @Override
diff --git a/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementConfig.java b/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementConfig.java
index 8faa95f2e78..e73ce2c043d 100644
--- a/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementConfig.java
+++ b/solr/core/src/java/org/apache/solr/cluster/placement/plugins/AffinityPlacementConfig.java
@@ -135,9 +135,8 @@ public class AffinityPlacementConfig implements PlacementPluginConfig {
   @JsonProperty public Boolean spreadAcrossDomains = Boolean.FALSE;
 
   /**
-   * Determines the maximum number of replicas of a particular type of a particular shard that can
-   * be placed within a single domain (as defined by the {@link #SPREAD_DOMAIN_SYSPROP} System
-   * property).
+   * Determines the maximum number of replicas of the same type from any given shard that may share
+   * a single domain (as defined by the {@link #SPREAD_DOMAIN_SYSPROP} System property).
    */
   @JsonProperty public Integer maxReplicasPerShardInDomain = -1;
 


(solr) 03/06: packaging: Remove docs/ from the Solr binary distribution (#4641)

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 60e1da7f9c01af726e72343bddcb031010c80728
Author: David Smiley <ds...@apache.org>
AuthorDate: Sat Jul 25 19:02:10 2026 -0400

    packaging: Remove docs/ from the Solr binary distribution (#4641)
    
    And add online links to README.txt
    
    (cherry picked from commit 047e14d9024a94aa814c228c79f39555d73748fb)
---
 .../unreleased/PR#4641-remove_docs_distro.yml      |  8 ++++
 dev-tools/scripts/smokeTestRelease.py              |  4 +-
 gradle/documentation/documentation.gradle          | 53 ++--------------------
 gradle/documentation/markdown.gradle               |  9 ----
 .../src/markdown/online-link.template.md           | 21 ---------
 solr/packaging/README.txt                          | 11 ++++-
 solr/packaging/build.gradle                        | 16 +++----
 7 files changed, 32 insertions(+), 90 deletions(-)

diff --git a/changelog/unreleased/PR#4641-remove_docs_distro.yml b/changelog/unreleased/PR#4641-remove_docs_distro.yml
new file mode 100644
index 00000000000..a95b65ec175
--- /dev/null
+++ b/changelog/unreleased/PR#4641-remove_docs_distro.yml
@@ -0,0 +1,8 @@
+title: >
+  Remove docs/ from the Solr binary distribution.  Add online links to such in README.txt
+type: other
+authors:
+  - name: David Smiley
+links:
+  - name: PR#4641
+    url: https://github.com/apache/solr/pull/4641
diff --git a/dev-tools/scripts/smokeTestRelease.py b/dev-tools/scripts/smokeTestRelease.py
index cd997b220b0..24a9e395e24 100755
--- a/dev-tools/scripts/smokeTestRelease.py
+++ b/dev-tools/scripts/smokeTestRelease.py
@@ -679,9 +679,9 @@ def verifyBinaryUnpacked(java, artifact, unpackPath, version, gitRevision):
   is_in_list(in_root_folder, ['LICENSE.txt', 'NOTICE.txt', 'README.txt', 'CHANGELOG.md'])
 
   if isSlim:
-    is_in_list(in_root_folder, ['bin', 'docker', 'docs', 'example', 'licenses', 'server', 'lib'])
+    is_in_list(in_root_folder, ['bin', 'docker', 'example', 'licenses', 'server', 'lib'])
   else:
-    is_in_list(in_root_folder, ['bin', 'modules', 'cross-dc-manager', 'docker', 'docs', 'example', 'licenses', 'server', 'lib'])
+    is_in_list(in_root_folder, ['bin', 'modules', 'cross-dc-manager', 'docker', 'example', 'licenses', 'server', 'lib'])
 
   if len(in_root_folder) > 0:
     raise RuntimeError('solr: unexpected files/dirs in artifact %s: %s' % (artifact, in_root_folder))
diff --git a/gradle/documentation/documentation.gradle b/gradle/documentation/documentation.gradle
index 8aa3f4a0bb0..700116ea13d 100644
--- a/gradle/documentation/documentation.gradle
+++ b/gradle/documentation/documentation.gradle
@@ -47,17 +47,14 @@ configure(rootProject) {
     group = 'documentation'
     description = 'Generate all documentation'
 
-    dependsOn ':solr:documentation:assemble'
+    dependsOn ':solr:documentation:documentation'
   }
-
-  assemble.dependsOn documentation
 }
 
 // docroot will point to Lucene and Solr relative directory for each sub-project.
 configure(project(':solr:documentation')) {
   ext {
     docroot = file("${buildDir}/site")
-    docrootMinimal = file("${buildDir}/minimalSite")
 
     markdownSrc = file("src/markdown")
     assets = file("src/assets")
@@ -80,12 +77,11 @@ configure(project(':solr:documentation')) {
     into project.docroot
   }
 
-  assemble {
-    dependsOn documentation
-  }
-
   configurations {
-    site
+    // Not part of 'assemble': only built on demand (e.g. by the release process or the ref guide build).
+    site {
+      visible = false
+    }
   }
 
   artifacts {
@@ -93,49 +89,10 @@ configure(project(':solr:documentation')) {
       builtBy documentation
     }
   }
-
-  task documentationMinimal() {
-    group = 'documentation'
-    description = "Generate stub Solr documentation pointing to web page (that's part of Solr TGZ)"
-    dependsOn 'copyMiniDocumentationAssets',
-        'createMiniDocumentationIndex',
-        'copyChangesToHtmlForMiniSite'
-  }
-
-  task copyChangesToHtmlForMiniSite(type: Copy) {
-    dependsOn 'copyDocumentationAssets'
-    dependsOn 'markdownToHtml'
-
-    from project.docroot
-    into project.docrootMinimal
-    include 'changes/**'
-    dependsOn 'changesToHtml'
-  }
-
-  task copyMiniDocumentationAssets(type: Copy) {
-    includeEmptyDirs = false
-    from('src/assets')
-    into project.docrootMinimal
-  }
-
-  assemble {
-    dependsOn documentationMinimal
-  }
-
-  configurations {
-    minimalSite
-  }
-
-  artifacts {
-    minimalSite project.docrootMinimal, {
-      builtBy documentationMinimal
-    }
-  }
 }
 
 configure(project(":solr")) {
   ext {
     docroot = project('documentation').docroot
-    docrootMinimal = project('documentation').docrootMinimal
   }
 }
diff --git a/gradle/documentation/markdown.gradle b/gradle/documentation/markdown.gradle
index 0506badfe8f..eb9458bdb9c 100644
--- a/gradle/documentation/markdown.gradle
+++ b/gradle/documentation/markdown.gradle
@@ -73,15 +73,6 @@ configure(project(':solr:documentation')) {
 
     withProjectList()
   }
-
-  task createMiniDocumentationIndex(type: MarkdownTemplateTask) {
-    outputFile = file("${project.docrootMinimal}/index.html")
-    templateFile = file("${project.markdownSrc}/online-link.template.md")
-
-    // list all properties used by the template here to allow uptodate checks to be correct:
-    inputs.property('version', project.version)
-    inputs.property('solrDocUrl', project.solrDocUrl).optional(true)
-  }
 }
 
 // filter that can be used with the "copy" task of Gradle that transforms Markdown files
diff --git a/solr/documentation/src/markdown/online-link.template.md b/solr/documentation/src/markdown/online-link.template.md
deleted file mode 100644
index 64f208719c9..00000000000
--- a/solr/documentation/src/markdown/online-link.template.md
+++ /dev/null
@@ -1,21 +0,0 @@
-<div>
-  <a href="https://solr.apache.org/">
-    <img src="solr.svg" style="width:210px; margin:22px 0px 7px 20px; border:none;" title="Apache Solr Logo" alt="Solr" />
-  </a>
-  <div style="z-index:100;position:absolute;top:25px;left:226px">
-    <span style="font-size: x-small">TM</span>
-  </div>
-</div>
-
-# Apache Solr™ ${project.version} Documentation
-
-<%
-if ("${project.version}" == "${project.baseVersion}") { // compare as strings because of lazy evaluation
-  println "Follow [this link to view online documentation](${project.solrDocUrl}) for Apache Solr ${project.version}."
-} else {
-  println "No online documentation available for custom builds or `SNAPSHOT` versions."
-  println "Run `gradlew documentation` from `src.tgz` package to build docs locally."
-}
-%>
-
-Review the [changes](changes/Changes.html) in Apache Solr ${project.version}.
diff --git a/solr/packaging/README.txt b/solr/packaging/README.txt
index 8c5a69cbd5e..7801ae00f49 100644
--- a/solr/packaging/README.txt
+++ b/solr/packaging/README.txt
@@ -81,8 +81,15 @@ docker/
   `docker/scripts` contains scripts that the Docker image uses to manage Solr.
   Refer to the README.md for instructions on how to build an image.
 
-docs/index.html
-  A link to the online version of Apache Solr Javadoc API documentation and Tutorial
+CHANGELOG.md
+  The list of changes in this release.
+
+Online Documentation
+  The online version of Apache Solr Javadoc API documentation and Tutorial:
+  @SOLR_DOC_URL@
+
+  Changes in this release are also published there, at:
+  @SOLR_CHANGES_URL@
 
 licenses/
   Licenses, notice files and signatures for Solr dependencies.
diff --git a/solr/packaging/build.gradle b/solr/packaging/build.gradle
index 72a8ddc42dc..6a1fa3ea1e1 100644
--- a/solr/packaging/build.gradle
+++ b/solr/packaging/build.gradle
@@ -15,6 +15,7 @@
  * limitations under the License.
  */
 
+import org.apache.tools.ant.filters.ReplaceTokens
 import org.apache.tools.ant.util.TeeOutputStream
 
 // This project puts together a "distribution", assembling dependencies from
@@ -33,6 +34,9 @@ ext {
   devDir = file("$buildDir/dev")
   slimDevDir = file("$buildDir/dev-slim")
   batsLibsDir = file("$buildDir/bats-libs")
+  onlineDocUnavailable = "Not available for custom/SNAPSHOT builds -- run './gradlew documentation' from the source distribution to build docs locally."
+  onlineDocUrl = (project.solrDocUrl ? "${project.solrDocUrl}/" : onlineDocUnavailable).toString()
+  onlineChangesUrl = (project.solrDocUrl ? "${project.solrDocUrl}/changes/Changes.html" : onlineDocUnavailable).toString()
 }
 
 configurations {
@@ -40,7 +44,6 @@ configurations {
   example
   crossDcManager
   server
-  docs
   docker
   solrFullTgz
   solrSlimTgz
@@ -58,9 +61,6 @@ dependencies {
   example project(path: ":solr:example", configuration: "packaging")
   server project(path: ":solr:server", configuration: "packaging")
 
-  // Copy files from documentation output
-  docs project(path: ':solr:documentation', configuration: 'minimalSite')
-
   docker project(path: ':solr:docker', configuration: 'packaging')
 
   solrFullTgzSignature files("$buildDir/distributions/solr-${version}.tgz.asc") {
@@ -92,6 +92,10 @@ distributions {
 
       from(projectDir, {
         include "README.txt"
+        filter(ReplaceTokens, tokens: [
+            SOLR_DOC_URL: onlineDocUrl,
+            SOLR_CHANGES_URL: onlineChangesUrl,
+        ])
       })
 
       from('static/lib', {
@@ -106,10 +110,6 @@ distributions {
         into "server"
       })
 
-      from(configurations.docs, {
-        into "docs"
-      })
-
       from(configurations.docker, {
         into "docker"
         filesMatching([


(solr) 02/06: SOLR-18310: opentelemetry: switch default from gRPC to http/protobuf(#4646)

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 1ec24a1c968c743f7c78bdd7166e50639fdefa71
Author: David Smiley <ds...@apache.org>
AuthorDate: Thu Jul 23 11:09:49 2026 -0400

    SOLR-18310: opentelemetry: switch default from gRPC to http/protobuf(#4646)
    
    opentelemetry: the default OTLP sender is now http/protobuf port 4318 and with fewer/no JARs to do so.
      JARs for others like gRPC have been removed but users can add as they need.  This reduces Netty JARs, for example.
    Affects metrics & tracing.
    
    Co-authored-by: copilot-swe-agent[bot] <19...@users.noreply.github.com>
    (cherry picked from commit 1e8116145faca028b08ac129fdf83e2d82091822)
---
 .../unreleased/SOLR-18310-otel-jdk-sender.yml      |  9 +++++++
 gradle/libs.versions.toml                          |  1 +
 .../solr/metrics/otel/MetricExporterFactory.java   |  2 +-
 solr/cross-dc-manager/gradle.lockfile              | 25 +------------------
 solr/licenses/grpc-netty-1.82.0.jar.sha1           |  1 -
 .../netty-codec-http2-4.2.15.Final.jar.sha1        |  1 -
 .../netty-codec-socks-4.2.15.Final.jar.sha1        |  1 -
 .../netty-handler-proxy-4.2.15.Final.jar.sha1      |  1 -
 ...entelemetry-exporter-sender-jdk-1.56.0.jar.sha1 |  1 +
 ...elemetry-exporter-sender-okhttp-1.56.0.jar.sha1 |  1 -
 .../proto-google-common-protos-2.64.1.jar.sha1     |  1 -
 solr/modules/opentelemetry/build.gradle            | 16 +++++--------
 solr/modules/opentelemetry/gradle.lockfile         | 28 ++--------------------
 .../solr/opentelemetry/OtelTracerConfigurator.java |  2 +-
 solr/server/etc/security.policy                    |  3 +++
 .../pages/distributed-tracing.adoc                 | 23 +++++++++++-------
 .../deployment-guide/pages/metrics-reporting.adoc  |  6 +++--
 .../pages/major-changes-in-solr-10.adoc            |  8 +++++++
 18 files changed, 52 insertions(+), 78 deletions(-)

diff --git a/changelog/unreleased/SOLR-18310-otel-jdk-sender.yml b/changelog/unreleased/SOLR-18310-otel-jdk-sender.yml
new file mode 100644
index 00000000000..93a8000d999
--- /dev/null
+++ b/changelog/unreleased/SOLR-18310-otel-jdk-sender.yml
@@ -0,0 +1,9 @@
+title: >
+  opentelemetry: the default OTLP sender is now http/protobuf port 4318 and with fewer/no JARs to do so.
+  JARs for others like gRPC have been removed but users can add as they need.
+type: dependency_update
+authors:
+  - name: David Smiley
+links:
+  - name: SOLR-18310
+    url: https://issues.apache.org/jira/browse/SOLR-18310
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 7612db4d50d..875029b49a4 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -487,6 +487,7 @@ opentelemetry-bom = { module = "io.opentelemetry:opentelemetry-bom", version.ref
 opentelemetry-context = { module = "io.opentelemetry:opentelemetry-context", version.ref = "opentelemetry" }
 opentelemetry-exporter-otlp = { module = "io.opentelemetry:opentelemetry-exporter-otlp", version.ref = "opentelemetry" }
 opentelemetry-exporter-prometheus = { module = "io.opentelemetry:opentelemetry-exporter-prometheus", version.ref = "opentelemetry-prometheus" }
+opentelemetry-exporter-sender-jdk = { module = "io.opentelemetry:opentelemetry-exporter-sender-jdk", version.ref = "opentelemetry" }
 opentelemetry-runtime-telemetry = { module = "io.opentelemetry.instrumentation:opentelemetry-runtime-telemetry-java17", version.ref = "opentelemetry-runtime-telemetry" }
 opentelemetry-sdk = { module = "io.opentelemetry:opentelemetry-sdk", version.ref = "opentelemetry" }
 opentelemetry-sdk-extension-autoconfigure = { module = "io.opentelemetry:opentelemetry-sdk-extension-autoconfigure", version.ref = "opentelemetry" }
diff --git a/solr/core/src/java/org/apache/solr/metrics/otel/MetricExporterFactory.java b/solr/core/src/java/org/apache/solr/metrics/otel/MetricExporterFactory.java
index d0ac8219aa3..e6f1f24e85c 100644
--- a/solr/core/src/java/org/apache/solr/metrics/otel/MetricExporterFactory.java
+++ b/solr/core/src/java/org/apache/solr/metrics/otel/MetricExporterFactory.java
@@ -25,7 +25,7 @@ public interface MetricExporterFactory {
       Boolean.parseBoolean(EnvUtils.getProperty("solr.metrics.otlpExporterEnabled", "false"));
 
   public static final String OTLP_EXPORTER_PROTOCOL =
-      EnvUtils.getProperty("solr.metrics.otlpExporterProtocol", "grpc");
+      EnvUtils.getProperty("solr.metrics.otlpExporterProtocol", "http");
 
   public static final int OTLP_EXPORTER_INTERVAL =
       Integer.parseInt(EnvUtils.getProperty("solr.metrics.otlpExporterInterval", "60000"));
diff --git a/solr/cross-dc-manager/gradle.lockfile b/solr/cross-dc-manager/gradle.lockfile
index 6cfa64f08d3..38c9acee2a1 100644
--- a/solr/cross-dc-manager/gradle.lockfile
+++ b/solr/cross-dc-manager/gradle.lockfile
@@ -19,8 +19,6 @@ com.fasterxml.woodstox:woodstox-core:7.2.1=jarValidation,runtimeClasspath,runtim
 com.github.ben-manes.caffeine:caffeine:3.2.4=annotationProcessor,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testRuntimeClasspath
 com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor
 com.github.luben:zstd-jni:1.5.6-4=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
-com.google.android:annotations:4.1.1.4=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.google.api.grpc:proto-google-common-protos:2.64.1=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
 com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
 com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
@@ -40,10 +38,6 @@ com.google.protobuf:protobuf-java:4.35.1=annotationProcessor,errorprone,jarValid
 com.j256.simplemagic:simplemagic:1.17=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 com.jayway.jsonpath:json-path:3.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 com.lmax:disruptor:4.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
-com.squareup.okhttp3:okhttp-jvm:5.4.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.squareup.okhttp3:okhttp:5.4.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.squareup.okio:okio-jvm:3.17.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.squareup.okio:okio:3.17.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 com.tdunning:t-digest:3.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 com.thoughtworks.paranamer:paranamer:2.8.3=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 com.typesafe.scala-logging:scala-logging_2.13:3.9.5=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
@@ -58,23 +52,9 @@ commons-validator:commons-validator:1.10.1=jarValidation,runtimeClasspath,runtim
 io.dropwizard.metrics:metrics-core:4.2.39=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor
 io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor
-io.grpc:grpc-api:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-context:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-core:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-netty:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-protobuf-lite:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-protobuf:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-stub:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-util:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.netty:netty-bom:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.netty:netty-buffer:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.netty:netty-codec-base:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
-io.netty:netty-codec-compression:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.netty:netty-codec-http2:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.netty:netty-codec-http:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.netty:netty-codec-socks:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.netty:netty-common:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
-io.netty:netty-handler-proxy:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.netty:netty-handler:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.netty:netty-resolver:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.netty:netty-tcnative-boringssl-static:2.0.79.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
@@ -97,7 +77,7 @@ io.opentelemetry:opentelemetry-exporter-common:1.56.0=jarValidation,runtimeClass
 io.opentelemetry:opentelemetry-exporter-otlp-common:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.opentelemetry:opentelemetry-exporter-otlp:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.opentelemetry:opentelemetry-exporter-prometheus:1.56.0-alpha=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
-io.opentelemetry:opentelemetry-exporter-sender-okhttp:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
+io.opentelemetry:opentelemetry-exporter-sender-jdk:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk-common:1.56.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
@@ -105,7 +85,6 @@ io.opentelemetry:opentelemetry-sdk-logs:1.56.0=jarValidation,runtimeClasspath,ru
 io.opentelemetry:opentelemetry-sdk-metrics:1.56.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk-trace:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
-io.perfmark:perfmark-api:0.27.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.prometheus:prometheus-metrics-exposition-formats:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 io.sgr:s2-geometry-library-java:1.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
@@ -215,8 +194,6 @@ org.glassfish.jersey.media:jersey-media-json-jackson:4.0.2=jarValidation,runtime
 org.glassfish.jersey:jersey-bom:4.0.2=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 org.hamcrest:hamcrest:3.0=jarValidation,testCompileClasspath,testRuntimeClasspath
 org.javassist:javassist:3.30.2-GA=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
-org.jetbrains.kotlin:kotlin-stdlib:2.2.21=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-org.jetbrains:annotations:26.1.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 org.jspecify:jspecify:1.0.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.6.2=jarValidation,testRuntimeClasspath
 org.junit.platform:junit-platform-commons:1.6.2=jarValidation,testRuntimeClasspath
diff --git a/solr/licenses/grpc-netty-1.82.0.jar.sha1 b/solr/licenses/grpc-netty-1.82.0.jar.sha1
deleted file mode 100644
index ad9bc971add..00000000000
--- a/solr/licenses/grpc-netty-1.82.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-bb2e92c518f044a194fbc06a769a1ec89efa3544
diff --git a/solr/licenses/netty-codec-http2-4.2.15.Final.jar.sha1 b/solr/licenses/netty-codec-http2-4.2.15.Final.jar.sha1
deleted file mode 100644
index 68fe44b7d9b..00000000000
--- a/solr/licenses/netty-codec-http2-4.2.15.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-c70540243427c8c952473f55813c6d459817de42
diff --git a/solr/licenses/netty-codec-socks-4.2.15.Final.jar.sha1 b/solr/licenses/netty-codec-socks-4.2.15.Final.jar.sha1
deleted file mode 100644
index 6adae698680..00000000000
--- a/solr/licenses/netty-codec-socks-4.2.15.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5d6dc38231104f28b6ba48b77d2f90b93cdb6fe7
diff --git a/solr/licenses/netty-handler-proxy-4.2.15.Final.jar.sha1 b/solr/licenses/netty-handler-proxy-4.2.15.Final.jar.sha1
deleted file mode 100644
index cdf1b264bb2..00000000000
--- a/solr/licenses/netty-handler-proxy-4.2.15.Final.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-31e63e04af11da75793ecbfc126d7691b8771d01
diff --git a/solr/licenses/opentelemetry-exporter-sender-jdk-1.56.0.jar.sha1 b/solr/licenses/opentelemetry-exporter-sender-jdk-1.56.0.jar.sha1
new file mode 100644
index 00000000000..4b0746ab0c9
--- /dev/null
+++ b/solr/licenses/opentelemetry-exporter-sender-jdk-1.56.0.jar.sha1
@@ -0,0 +1 @@
+a444a2c56f7b40cbde39bc542523a912811b7d97
diff --git a/solr/licenses/opentelemetry-exporter-sender-okhttp-1.56.0.jar.sha1 b/solr/licenses/opentelemetry-exporter-sender-okhttp-1.56.0.jar.sha1
deleted file mode 100644
index 7aaf975e4de..00000000000
--- a/solr/licenses/opentelemetry-exporter-sender-okhttp-1.56.0.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-5cc7baa0fe03a47f1af52193f480b7d9d8d2a767
diff --git a/solr/licenses/proto-google-common-protos-2.64.1.jar.sha1 b/solr/licenses/proto-google-common-protos-2.64.1.jar.sha1
deleted file mode 100644
index 371f2bdcaaa..00000000000
--- a/solr/licenses/proto-google-common-protos-2.64.1.jar.sha1
+++ /dev/null
@@ -1 +0,0 @@
-a71d9a9867ed792e54e893b8c7864a0ba1b022cf
diff --git a/solr/modules/opentelemetry/build.gradle b/solr/modules/opentelemetry/build.gradle
index b14d3868e41..49877fbcd93 100644
--- a/solr/modules/opentelemetry/build.gradle
+++ b/solr/modules/opentelemetry/build.gradle
@@ -23,7 +23,6 @@ dependencies {
   implementation platform(project(':platform'))
   implementation project(':solr:core')
 
-  implementation platform(libs.netty.bom)
   implementation platform(libs.opentelemetry.bom)
 
   implementation libs.slf4j.api
@@ -32,16 +31,13 @@ dependencies {
   implementation libs.opentelemetry.sdk
   implementation libs.opentelemetry.sdk.metrics
   implementation libs.opentelemetry.sdk.extension.autoconfigure
-  implementation libs.opentelemetry.exporter.otlp
-  // End users must recompile with jaeger exporter and/or zipkin exporter if they need these
+  implementation(libs.opentelemetry.exporter.otlp) {
+    // Exclude the OkHttp-based sender; we use the JDK HTTP sender instead
+    exclude group: 'io.opentelemetry', module: 'opentelemetry-exporter-sender-okhttp'
+  }
 
-  // NOTE: sdk-autoconfigure needs both opentelemetry-sdk-metrics and opentelemetry-sdk-logs even if we don't use them
-
-  // gRPC transport via netty - since we already ship netty this is more lightweight than netty-shaded
-  runtimeOnly libs.grpc.netty
-  runtimeOnly libs.grpc.protobuf
-  runtimeOnly libs.grpc.stub
-  runtimeOnly libs.grpc.context
+  // OTLP HTTP sender that requires no additional dependencies.
+  runtimeOnly libs.opentelemetry.exporter.sender.jdk
   // See https://issues.apache.org/jira/browse/LOG4J2-3609 due to needing these annotations
   compileOnly libs.apache.tomcat.annotationsapi
 
diff --git a/solr/modules/opentelemetry/gradle.lockfile b/solr/modules/opentelemetry/gradle.lockfile
index 71dacc034cb..a18c63f3796 100644
--- a/solr/modules/opentelemetry/gradle.lockfile
+++ b/solr/modules/opentelemetry/gradle.lockfile
@@ -14,12 +14,9 @@ com.fasterxml.jackson:jackson-bom:2.22.0=compileClasspath,jarValidation,runtimeC
 com.fasterxml.woodstox:woodstox-core:7.2.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 com.github.ben-manes.caffeine:caffeine:3.2.4=annotationProcessor,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testRuntimeClasspath
 com.github.kevinstern:software-and-algorithms:1.0=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.android:annotations:4.1.1.4=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.google.api.grpc:proto-google-common-protos:2.64.1=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 com.google.auto.service:auto-service-annotations:1.0.1=annotationProcessor,errorprone,testAnnotationProcessor
 com.google.auto.value:auto-value-annotations:1.11.1=annotationProcessor,errorprone,testAnnotationProcessor
 com.google.auto:auto-common:1.2.2=annotationProcessor,errorprone,testAnnotationProcessor
-com.google.code.gson:gson:2.14.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 com.google.errorprone:error_prone_annotation:2.41.0=annotationProcessor,errorprone,testAnnotationProcessor
 com.google.errorprone:error_prone_annotations:2.47.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 com.google.errorprone:error_prone_annotations:2.49.0=annotationProcessor,errorprone,testAnnotationProcessor
@@ -30,14 +27,10 @@ com.google.guava:failureaccess:1.0.3=annotationProcessor,compileClasspath,errorp
 com.google.guava:guava:33.6.0-jre=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
 com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
 com.google.j2objc:j2objc-annotations:3.1=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
-com.google.protobuf:protobuf-java:4.35.1=annotationProcessor,errorprone,jarValidation,runtimeClasspath,runtimeLibs,testAnnotationProcessor,testRuntimeClasspath
+com.google.protobuf:protobuf-java:4.35.1=annotationProcessor,errorprone,testAnnotationProcessor
 com.j256.simplemagic:simplemagic:1.17=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 com.jayway.jsonpath:json-path:3.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 com.lmax:disruptor:4.0.0=solrPlatformLibs
-com.squareup.okhttp3:okhttp-jvm:5.4.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.squareup.okhttp3:okhttp:5.4.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.squareup.okio:okio-jvm:3.17.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-com.squareup.okio:okio:3.17.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 com.tdunning:t-digest:3.3=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 commons-cli:commons-cli:1.11.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 commons-codec:commons-codec:1.22.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
@@ -45,23 +38,9 @@ commons-io:commons-io:2.22.0=compileClasspath,jarValidation,runtimeClasspath,run
 io.dropwizard.metrics:metrics-core:4.2.39=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 io.github.eisop:dataflow-errorprone:3.41.0-eisop1=annotationProcessor,errorprone,testAnnotationProcessor
 io.github.java-diff-utils:java-diff-utils:4.12=annotationProcessor,errorprone,testAnnotationProcessor
-io.grpc:grpc-api:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-context:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-core:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-netty:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-protobuf-lite:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-protobuf:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-stub:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.grpc:grpc-util:1.82.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.netty:netty-bom:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
 io.netty:netty-buffer:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.netty:netty-codec-base:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
-io.netty:netty-codec-compression:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.netty:netty-codec-http2:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.netty:netty-codec-http:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-io.netty:netty-codec-socks:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.netty:netty-common:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
-io.netty:netty-handler-proxy:4.2.15.Final=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.netty:netty-handler:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.netty:netty-resolver:4.2.15.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.netty:netty-tcnative-boringssl-static:2.0.79.Final=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
@@ -84,7 +63,7 @@ io.opentelemetry:opentelemetry-exporter-common:1.56.0=jarValidation,runtimeClass
 io.opentelemetry:opentelemetry-exporter-otlp-common:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.opentelemetry:opentelemetry-exporter-otlp:1.56.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
 io.opentelemetry:opentelemetry-exporter-prometheus:1.56.0-alpha=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
-io.opentelemetry:opentelemetry-exporter-sender-okhttp:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
+io.opentelemetry:opentelemetry-exporter-sender-jdk:1.56.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk-common:1.56.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk-extension-autoconfigure-spi:1.56.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk-extension-autoconfigure:1.56.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,testCompileClasspath,testRuntimeClasspath
@@ -93,7 +72,6 @@ io.opentelemetry:opentelemetry-sdk-metrics:1.56.0=compileClasspath,jarValidation
 io.opentelemetry:opentelemetry-sdk-testing:1.56.0=jarValidation,testCompileClasspath,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk-trace:1.56.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
 io.opentelemetry:opentelemetry-sdk:1.56.0=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
-io.perfmark:perfmark-api:0.27.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 io.prometheus:prometheus-metrics-exposition-formats:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 io.prometheus:prometheus-metrics-model:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 io.sgr:s2-geometry-library-java:1.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
@@ -180,8 +158,6 @@ org.glassfish.jersey.media:jersey-media-json-jackson:4.0.2=jarValidation,runtime
 org.glassfish.jersey:jersey-bom:4.0.2=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
 org.hamcrest:hamcrest:3.0=jarValidation,testCompileClasspath,testRuntimeClasspath
 org.javassist:javassist:3.30.2-GA=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
-org.jetbrains.kotlin:kotlin-stdlib:2.2.21=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
-org.jetbrains:annotations:26.1.0=jarValidation,runtimeClasspath,runtimeLibs,testRuntimeClasspath
 org.jspecify:jspecify:1.0.0=annotationProcessor,compileClasspath,errorprone,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testAnnotationProcessor,testCompileClasspath,testRuntimeClasspath
 org.junit.jupiter:junit-jupiter-api:5.6.2=jarValidation,testRuntimeClasspath
 org.junit.platform:junit-platform-commons:1.6.2=jarValidation,testRuntimeClasspath
diff --git a/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java b/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
index c70acee63c2..ae1aa625991 100644
--- a/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
+++ b/solr/modules/opentelemetry/src/java/org/apache/solr/opentelemetry/OtelTracerConfigurator.java
@@ -71,7 +71,7 @@ public class OtelTracerConfigurator extends OpenTelemetryConfigurator {
     injectPluginSettingsIfNotConfigured(args);
     setDefaultIfNotConfigured("OTEL_SERVICE_NAME", "solr");
     setDefaultIfNotConfigured("OTEL_TRACES_EXPORTER", "otlp");
-    setDefaultIfNotConfigured("OTEL_EXPORTER_OTLP_PROTOCOL", "grpc");
+    setDefaultIfNotConfigured("OTEL_EXPORTER_OTLP_PROTOCOL", "http/protobuf");
     setDefaultIfNotConfigured("OTEL_TRACES_SAMPLER", "parentbased_always_on");
     setDefaultIfNotConfigured("OTEL_PROPAGATORS", "tracecontext,baggage");
     if (EnvUtils.getProperty("host") != null) {
diff --git a/solr/server/etc/security.policy b/solr/server/etc/security.policy
index f932cc0b461..2dd03af0be2 100644
--- a/solr/server/etc/security.policy
+++ b/solr/server/etc/security.policy
@@ -215,6 +215,9 @@ grant {
 
   // expanded to a wildcard if set, allows all networking everywhere
   permission java.net.SocketPermission "${solr.internal.network.permission}", "accept,listen,connect,resolve";
+  // java.net.http.HttpClient requires URLPermission separately from SocketPermission above.
+  permission java.net.URLPermission "http://${solr.internal.network.permission}:*/-", "*:*";
+  permission java.net.URLPermission "https://${solr.internal.network.permission}:*/-", "*:*";
 
   // CUDA for GPU module (cuVS)
   permission java.lang.RuntimePermission "loadLibrary.cudart";
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/distributed-tracing.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/distributed-tracing.adoc
index fb4cdb050cc..fb60329ee03 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/pages/distributed-tracing.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/distributed-tracing.adoc
@@ -18,7 +18,10 @@
 
 Solr includes a general tracing framework based on OpenTracing that can be used to trace the lifecycle of a request for performance monitoring.
 
-Tracing data can be configured to send to various backends, either directly or via an agent. Solr can send traces directly in OTLP/gRPC format. You can support many other destinations and cloud providers by installing an agent on each node and sending traces to localhost.
+Tracing data can be configured to send to various backends, either directly or via an agent.
+Solr can send traces directly in OTLP/HTTP format with the opentelemetry module, out-of-the-box.
+Other protocols, destinations and cloud providers may be supported.
+For example, gRPC can be supported by adding more JARs and tweaking configuration.
 
 A sampled distributed tracing query request displayed in Jaeger UI looks like this:
 
@@ -39,7 +42,7 @@ This plugin can be disabled by setting the `solr.tracing.always.on.enabled` syst
 The `TracerConfigurator` is a class used to provide an instance of `io.opentracing.Tracer` based on configuration in `solr.xml`.
 These are pluggable, and each plugin is shipped as a xref:configuration-guide:solr-modules.adoc[Solr Module]:
 
-**opentelemetry**: The `opentelemetry` module supports OTLP over gRPC or HTTP.
+**opentelemetry**: The `opentelemetry` module supports OTLP over HTTP.
 
 A setup of a `TracerConfigurator` in `solr.xml` looks like this:
 
@@ -55,7 +58,8 @@ By doing this, some backends like DataDog are supported out of the box since htt
 
 == Open Telemetry Module
 
-This module brings support for the industry standard https://opentelemetry.io[OpenTelemetry] (or short "OTEL") tracing, and exposes a tracer configurator that can be enabled in the `<tracerConfig>` tag of `solr.xml` as follows:
+This module brings support for the industry standard https://opentelemetry.io[OpenTelemetry] ("OTEL").
+OTEL is broader than tracing, but nonetheless, Solr's focal configuration element for it in Solr is `<tracerConfig>` in `solr.xml` as follows:
 
 [source,xml]
 ----
@@ -70,24 +74,27 @@ Enable the module with either system property `-Dsolr.modules=opentelemetry` or
 
 The tracer can be configured through environment variables or Java system properties, see https://opentelemetry.io/docs/reference/specification/sdk-environment-variables/[OTEL SDK Environment Variables] and https://github.com/open-telemetry/opentelemetry-java/blob/v{dep-version-opentelemetry}/sdk-extensions/autoconfigure/README.md[Java SDK Autoconfigure].
 
-The default configuration will ship traces to a collector running on localhost, using https://opentelemetry.io/docs/reference/specification/protocol/[OTLP] over https://grpc.io[gRPC], and will propagate trace IDs using https://www.w3.org/TR/trace-context/[W3C TraceContext]. Here are the environment settings that are enabled by default:
+The default configuration will ship traces to a collector running on localhost, using https://opentelemetry.io/docs/reference/specification/protocol/[OTLP] over HTTP (Protobuf), and will propagate trace IDs using https://www.w3.org/TR/trace-context/[W3C TraceContext]. Here are the environment settings that are enabled by default:
 
 [source,bash]
 ----
 OTEL_SDK_DISABLED=false
 OTEL_SERVICE_NAME=solr
 OTEL_TRACES_EXPORTER=otlp
-OTEL_EXPORTER_OTLP_PROTOCOL=grpc
-OTEL_EXPORTER_OTLP_ENDPOINT=localhost:4317
+OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
+OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
 OTEL_TRACES_SAMPLER=parentbased_always_on
 OTEL_PROPAGATORS=tracecontext,baggage
 ----
 
+NOTE: gRPC transport is not supported out of the box.
+To use gRPC, add the required gRPC and Netty JARs to the `opentelemetry` module's lib directory and set `OTEL_EXPORTER_OTLP_PROTOCOL=grpc`.
+
 Say you want to send traces to a remote https://opentelemetry.io/docs/collector/[OTEL Collector], with 10% sampling. That could be done with this configuration:
 
 [source,bash]
 ----
-OTEL_EXPORTER_OTLP_ENDPOINT=my-remote-collector:4317
+OTEL_EXPORTER_OTLP_ENDPOINT=http://my-remote-collector:4318
 OTEL_TRACES_SAMPLER=parentbased_traceidratio
 OTEL_TRACES_SAMPLER_ARG=0.1
 ----
@@ -96,7 +103,7 @@ An equivalent configuration using system properties would be:
 
 [source,bash]
 ----
-SOLR_OPTS=-Dotel.exporter.otlp.endpoint=my-remote-collector:4317 -Dotel.traces.sampler=parentbased_traceidratio -Dotel.traces.sampler.arg=0.1
+SOLR_OPTS=-Dotel.exporter.otlp.endpoint=http://my-remote-collector:4318 -Dotel.traces.sampler=parentbased_traceidratio -Dotel.traces.sampler.arg=0.1
 ----
 
 To add custom tags to the trace, use `OTEL_RESOURCE_ATTRIBUTES`:
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc
index 15a2d592f87..adab8021580 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/metrics-reporting.adoc
@@ -312,7 +312,7 @@ http://localhost:8983/api/metrics?name=solr_core_index_size_bytes&collection=foo
 
 == OTLP
 
-For users who do not use or support pulling metrics in Prometheus format with the `/metrics` API, Solr also supports pushing metrics natively with https://opentelemetry.io/docs/specs/otlp/[OTLP], which is a vendor-agnostic protocol for pushing metrics via gRPC or HTTP.
+For users who do not use or support pulling metrics in Prometheus format with the `/metrics` API, Solr also supports pushing metrics natively with https://opentelemetry.io/docs/specs/otlp/[OTLP], which is a vendor-agnostic protocol for pushing metrics.
 
 OTLP is widely supported by many tools, vendors, and pipelines. See the OpenTelemetry https://opentelemetry.io/ecosystem/vendors/[vendors list] for more details on available and compatible options.
 
@@ -341,11 +341,13 @@ Boolean value to enable or disable the OTLP metrics exporter.
 +
 [%autowidth,frame=none]
 |===
-|Optional |Default: grpc
+|Optional |Default: http
 |===
 +
 OTLP protocol to use for pushing metrics. Available options are `grpc`, `http`, or `none` (disabled).
 
+NOTE: gRPC is not supported out of the box. To use it, add the required gRPC and Netty JARs to the `opentelemetry` module's lib directory.
+
 `solr.metrics.otlpExporterInterval`::
 +
 [%autowidth,frame=none]
diff --git a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
index 234a9666b6f..80acfeae06a 100644
--- a/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
+++ b/solr/solr-ref-guide/modules/upgrade-notes/pages/major-changes-in-solr-10.adoc
@@ -382,6 +382,14 @@ A new feature vector cache was added that is used not only for feature logging b
 
 The new OTEL based metric system introduced in 10.0 is considered BETA, and some breaking changes are to be expected in this and coming minor releases.
 
+==== OTLP protocols
+
+The `opentelemetry` module no longer includes some dependencies, dropping gRPC support out-of-the-box.
+The default export protocol for tracing has changed from `grpc` to `http/protobuf` (OTLP port `4318` instead of `4317`).
+The default for the separate OTLP metrics exporter's `solr.metrics.otlpExporterProtocol` has likewise changed from `grpc` to `http`.
+
+Use of gRPC can be restored by adding the required gRPC & Netty jars to the `opentelemetry` module's lib directory, and setting `OTEL_EXPORTER_OTLP_PROTOCOL=grpc` (tracing) and/or `solr.metrics.otlpExporterProtocol=grpc` (metrics) as needed.
+
 ==== OTLP Metric Names Changed to Dot-Separated Format
 
 *Breaking change for OTLP consumers.*


(solr) 05/06: SOLR-18248 : Migration of Tasks V2 APIs to JAX-RS Constructs (#4452)

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7e636dc2c10dc71b5122fb3db279a0e18b261ff5
Author: Jalaz Kumar <ja...@gmail.com>
AuthorDate: Sun Jul 26 20:33:06 2026 +0530

    SOLR-18248 : Migration of Tasks V2 APIs to JAX-RS Constructs (#4452)
    
    Co-authored-by: Eric Pugh <ep...@opensourceconnections.com>
    (cherry picked from commit a60886fb38a919161daa5592f04bdc68eb4b4053)
---
 changelog/unreleased/SOLR-18248-list-tasks.yml     |   8 +
 .../apache/solr/client/api/endpoint/TasksApi.java  |  47 ++++++
 .../solr/client/api/model/ActiveTaskDetails.java   |  33 +++++
 .../client/api/model/ListActiveTaskResponse.java   |  25 ++++
 .../solr/client/api/model/TaskStatusResponse.java  |  40 +++++
 .../solr/handler/admin/HealthCheckHandler.java     |   3 -
 .../apache/solr/handler/admin/api/ActiveTask.java  |  85 +++++++++++
 .../solr/handler/admin/api/ListActiveTasksAPI.java |  48 ------
 .../handler/component/ActiveTaskQuerySupport.java  | 165 +++++++++++++++++++++
 .../component/ActiveTasksListComponent.java        | 128 ----------------
 .../handler/component/ActiveTasksListHandler.java  |  64 ++++----
 .../handler/component/TaskManagementHandler.java   |   3 -
 .../solr/handler/admin/api/ActiveTaskTest.java     | 100 +++++++++++++
 .../org/apache/solr/search/TestTaskManagement.java | 116 +++++++++++++++
 .../deployment-guide/pages/task-management.adoc    |  62 +++++++-
 15 files changed, 711 insertions(+), 216 deletions(-)

diff --git a/changelog/unreleased/SOLR-18248-list-tasks.yml b/changelog/unreleased/SOLR-18248-list-tasks.yml
new file mode 100644
index 00000000000..3dc9716c12c
--- /dev/null
+++ b/changelog/unreleased/SOLR-18248-list-tasks.yml
@@ -0,0 +1,8 @@
+title: Migrated ListTasks API & TaskStatus API from homegrown @EndPoint to JAX-RS
+type: added
+authors:
+  - name: Jalaz Kumar
+  - name: Eric Pugh
+links:
+  - name: SOLR-18248
+    url: https://issues.apache.org/jira/browse/SOLR-18248
diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/TasksApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/TasksApi.java
new file mode 100644
index 00000000000..3e46c1465c6
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/TasksApi.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.endpoint;
+
+import static org.apache.solr.client.api.util.Constants.INDEX_PATH_PREFIX;
+
+import io.swagger.v3.oas.annotations.Operation;
+import jakarta.ws.rs.GET;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import org.apache.solr.client.api.model.ListActiveTaskResponse;
+import org.apache.solr.client.api.model.TaskStatusResponse;
+import org.apache.solr.client.api.util.StoreApiParameters;
+
+@Path(INDEX_PATH_PREFIX + "/tasks")
+public interface TasksApi {
+
+  @GET
+  @StoreApiParameters
+  @Operation(
+      summary = "Lists all the active tasks",
+      tags = {"tasks"})
+  ListActiveTaskResponse listAllActiveTasks() throws Exception;
+
+  @GET
+  @Path("/{taskID}")
+  @StoreApiParameters
+  @Operation(
+      summary = "Status of a specific task",
+      tags = {"tasks"})
+  TaskStatusResponse getTaskStatus(@PathParam("taskID") String taskID) throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java b/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java
new file mode 100644
index 00000000000..b4edb2b9efb
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/ActiveTaskDetails.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class ActiveTaskDetails {
+
+  public ActiveTaskDetails() {}
+
+  public ActiveTaskDetails(String id, String query) {
+    this.id = id;
+    this.query = query;
+  }
+
+  @JsonProperty public String id;
+  @JsonProperty public String query;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/ListActiveTaskResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/ListActiveTaskResponse.java
new file mode 100644
index 00000000000..c7d7841216b
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/ListActiveTaskResponse.java
@@ -0,0 +1,25 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+public class ListActiveTaskResponse extends SolrJerseyResponse {
+  @JsonProperty public List<ActiveTaskDetails> tasks;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java
new file mode 100644
index 00000000000..9ca07c014e4
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/TaskStatusResponse.java
@@ -0,0 +1,40 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class TaskStatusResponse extends SolrJerseyResponse {
+
+  public enum TaskStatus {
+    ACTIVE("active"),
+    INACTIVE("inactive");
+
+    private final String value;
+
+    TaskStatus(String value) {
+      this.value = value;
+    }
+
+    public String getValue() {
+      return this.value;
+    }
+  }
+
+  @JsonProperty public TaskStatus status;
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/HealthCheckHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/HealthCheckHandler.java
index 1dab5d1d977..8c73ac11af3 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/HealthCheckHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/HealthCheckHandler.java
@@ -59,9 +59,6 @@ import org.apache.solr.security.AuthorizationContext;
  * specify the acceptable generation lag follower should be with respect to its leader using the
  * <code>maxGenerationLag=&lt;max_generation_lag&gt;</code> request parameter. If <code>
  * maxGenerationLag</code> is not provided then health check would simply return OK.
- *
- * <p>All health-check logic lives in the v2 {@link NodeHealth}; this handler is a thin v1 bridge
- * that extracts request parameters and delegates.
  */
 public class HealthCheckHandler extends RequestHandlerBase {
 
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java
new file mode 100644
index 00000000000..6ed8fa001fd
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/ActiveTask.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import static org.apache.solr.security.PermissionNameProvider.Name.READ_PERM;
+
+import jakarta.inject.Inject;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.client.api.endpoint.TasksApi;
+import org.apache.solr.client.api.model.ActiveTaskDetails;
+import org.apache.solr.client.api.model.ListActiveTaskResponse;
+import org.apache.solr.client.api.model.TaskStatusResponse;
+import org.apache.solr.handler.component.ActiveTaskQuerySupport;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.request.SolrQueryRequest;
+
+public class ActiveTask extends JerseyResource implements TasksApi {
+
+  private final SolrQueryRequest solrQueryRequest;
+
+  @Inject
+  public ActiveTask(SolrQueryRequest solrQueryRequest) {
+    this.solrQueryRequest = solrQueryRequest;
+  }
+
+  @Override
+  @PermissionName(READ_PERM)
+  public ListActiveTaskResponse listAllActiveTasks() throws Exception {
+    final ListActiveTaskResponse response = instantiateJerseyResponse(ListActiveTaskResponse.class);
+    response.tasks = ActiveTaskQuerySupport.listActiveTasks(solrQueryRequest);
+    return response;
+  }
+
+  @Override
+  @PermissionName(READ_PERM)
+  public TaskStatusResponse getTaskStatus(String taskID) throws Exception {
+    final TaskStatusResponse response = instantiateJerseyResponse(TaskStatusResponse.class);
+
+    boolean isTaskActive = ActiveTaskQuerySupport.isTaskActive(solrQueryRequest, taskID);
+
+    response.status =
+        (isTaskActive)
+            ? TaskStatusResponse.TaskStatus.ACTIVE
+            : TaskStatusResponse.TaskStatus.INACTIVE;
+
+    return response;
+  }
+
+  public static List<ActiveTaskDetails> getActiveTasksOnThisShard(
+      SolrQueryRequest solrQueryRequest) {
+    Iterator<Map.Entry<String, String>> iterator =
+        solrQueryRequest.getCore().getCancellableQueryTracker().getActiveQueriesGenerated();
+
+    List<ActiveTaskDetails> activeTaskDetails = new ArrayList<>();
+    while (iterator.hasNext()) {
+      Map.Entry<String, String> entry = iterator.next();
+      activeTaskDetails.add(new ActiveTaskDetails(entry.getKey(), entry.getValue()));
+    }
+
+    return activeTaskDetails;
+  }
+
+  public static boolean isTaskActiveOnThisShard(SolrQueryRequest solrQueryRequest, String taskId) {
+    return solrQueryRequest.getCore().getCancellableQueryTracker().isQueryIdActive(taskId);
+  }
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasksAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasksAPI.java
deleted file mode 100644
index fba3d9d26f3..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/ListActiveTasksAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.component.ActiveTasksListHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API for listing any currently running "tasks".
- *
- * <p>This API (GET /v2/collections/collectionName/tasks/list) is analogous to the v1
- * /solr/collectionName/tasks/list API.
- */
-public class ListActiveTasksAPI {
-  private final ActiveTasksListHandler listTaskHandler;
-
-  public ListActiveTasksAPI(ActiveTasksListHandler listTaskHandler) {
-    this.listTaskHandler = listTaskHandler;
-  }
-
-  @EndPoint(
-      path = {"/tasks/list"},
-      method = GET,
-      permission = PermissionNameProvider.Name.READ_PERM)
-  public void listActiveTasks(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    listTaskHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ActiveTaskQuerySupport.java b/solr/core/src/java/org/apache/solr/handler/component/ActiveTaskQuerySupport.java
new file mode 100644
index 00000000000..e1da0f6bb44
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/component/ActiveTaskQuerySupport.java
@@ -0,0 +1,165 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.solr.handler.component;
+
+import static org.apache.solr.common.params.CommonParams.DISTRIB;
+import static org.apache.solr.common.params.CommonParams.QT;
+import static org.apache.solr.common.params.CommonParams.TASK_CHECK_UUID;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.solr.client.api.model.ActiveTaskDetails;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.ModifiableSolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.CoreContainer;
+import org.apache.solr.handler.admin.api.ActiveTask;
+import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.response.SolrQueryResponse;
+
+public class ActiveTaskQuerySupport {
+  private static final String ACTIVE_TASK_LIST_HANDLER_PATH = "/tasks/list";
+
+  private ActiveTaskQuerySupport() {}
+
+  public static List<ActiveTaskDetails> listActiveTasks(SolrQueryRequest req) throws Exception {
+    return execute(req, null).taskList;
+  }
+
+  public static boolean isTaskActive(SolrQueryRequest req, String taskId) throws Exception {
+    return execute(req, taskId).taskActive;
+  }
+
+  private static TaskQueryResult execute(SolrQueryRequest req, String taskId) throws Exception {
+    if (!shouldDistributed(req)) {
+      return localResult(req, taskId);
+    }
+    return distributedResult(req, taskId);
+  }
+
+  private static TaskQueryResult localResult(SolrQueryRequest req, String taskId) {
+    if (taskId != null) {
+      return new TaskQueryResult(List.of(), ActiveTask.isTaskActiveOnThisShard(req, taskId));
+    }
+    return new TaskQueryResult(ActiveTask.getActiveTasksOnThisShard(req), false);
+  }
+
+  private static TaskQueryResult distributedResult(SolrQueryRequest req, String taskId)
+      throws Exception {
+    final ShardHandler shardHandler =
+        req.getCoreContainer().getShardHandlerFactory().getShardHandler();
+    final ResponseBuilder responseBuilder =
+        TaskManagementHandler.buildResponseBuilder(req, new SolrQueryResponse(), List.of());
+    shardHandler.prepDistributed(responseBuilder);
+
+    if (!responseBuilder.isDistrib
+        || responseBuilder.shards == null
+        || responseBuilder.shards.length == 0) {
+      return localResult(req, taskId);
+    }
+
+    final ShardRequest shardRequest = new ShardRequest();
+    shardRequest.shards = responseBuilder.shards;
+    shardRequest.actualShards = shardRequest.shards;
+    shardRequest.responses = new ArrayList<>(shardRequest.actualShards.length);
+
+    for (String shard : shardRequest.actualShards) {
+      ModifiableSolrParams params = new ModifiableSolrParams();
+      params.set(QT, ACTIVE_TASK_LIST_HANDLER_PATH);
+      if (taskId != null) {
+        params.set(TASK_CHECK_UUID, taskId);
+      }
+      ShardHandler.setShardAttributesToParams(params, shardRequest.purpose);
+      shardHandler.submit(shardRequest, shard, params);
+    }
+
+    ShardResponse shardResponse = shardHandler.takeCompletedOrError();
+    if (shardResponse != null && shardResponse.getShard() != null) {
+      if (shardResponse.getException() != null) {
+        shardHandler.cancelAll();
+        if (shardResponse.getException() instanceof SolrException) {
+          throw (SolrException) shardResponse.getException();
+        }
+        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, shardResponse.getException());
+      }
+    }
+
+    if (taskId != null) {
+      return new TaskQueryResult(List.of(), mergeTaskStatus(shardRequest.responses));
+    }
+    return new TaskQueryResult(mergeTaskList(shardRequest.responses), false);
+  }
+
+  private static boolean shouldDistributed(SolrQueryRequest req) {
+    CoreContainer coreContainer = req.getCoreContainer();
+    if (coreContainer == null) {
+      return false;
+    }
+    return req.getParams().getBool(DISTRIB, coreContainer.isZooKeeperAware());
+  }
+
+  private static boolean mergeTaskStatus(List<ShardResponse> responses) {
+    for (ShardResponse shardResponse : responses) {
+      Object taskStatus = shardResponse.getSolrResponse().getResponse().get("taskStatus");
+      if (taskStatus instanceof Boolean && (Boolean) taskStatus) {
+        return true;
+      }
+
+      if (taskStatus instanceof String && ((String) taskStatus).contains("active")) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @SuppressWarnings("unchecked")
+  private static List<ActiveTaskDetails> mergeTaskList(List<ShardResponse> responses) {
+    Map<String, String> mergedTasks = new LinkedHashMap<>();
+    for (ShardResponse shardResponse : responses) {
+      Object taskList = shardResponse.getSolrResponse().getResponse().get("taskList");
+      if (taskList instanceof NamedList) {
+        NamedList<Object> namedList = (NamedList<Object>) taskList;
+        for (int i = 0; i < namedList.size(); i++) {
+          String taskId = namedList.getName(i);
+          Object taskQuery = namedList.getVal(i);
+          if (taskId != null) {
+            mergedTasks.put(taskId, taskQuery == null ? null : taskQuery.toString());
+          }
+        }
+      }
+    }
+
+    List<ActiveTaskDetails> mergedTaskList = new ArrayList<>(mergedTasks.size());
+    for (Map.Entry<String, String> task : mergedTasks.entrySet()) {
+      mergedTaskList.add(new ActiveTaskDetails(task.getKey(), task.getValue()));
+    }
+
+    return mergedTaskList;
+  }
+
+  private static final class TaskQueryResult {
+    private final List<ActiveTaskDetails> taskList;
+    private final boolean taskActive;
+
+    private TaskQueryResult(List<ActiveTaskDetails> taskList, boolean taskActive) {
+      this.taskList = taskList;
+      this.taskActive = taskActive;
+    }
+  }
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListComponent.java b/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListComponent.java
deleted file mode 100644
index ce8a31335c2..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListComponent.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.handler.component;
-
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import org.apache.solr.common.MapWriter;
-import org.apache.solr.common.util.NamedList;
-
-/** List the active tasks that can be cancelled */
-public class ActiveTasksListComponent extends SearchComponent {
-  public static final String COMPONENT_NAME = "activetaskslist";
-
-  private boolean shouldProcess;
-
-  @Override
-  public void prepare(ResponseBuilder rb) throws IOException {
-    if (rb.isTaskListRequest()) {
-      shouldProcess = true;
-    }
-  }
-
-  @Override
-  public void process(ResponseBuilder rb) {
-    if (!shouldProcess) {
-      return;
-    }
-
-    if (rb.getTaskStatusCheckUUID() != null) {
-      boolean isActiveOnThisShard =
-          rb.req
-              .getCore()
-              .getCancellableQueryTracker()
-              .isQueryIdActive(rb.getTaskStatusCheckUUID());
-
-      rb.rsp.add("taskStatus", isActiveOnThisShard);
-      return;
-    }
-
-    rb.rsp.add(
-        "taskList",
-        (MapWriter)
-            ew -> {
-              Iterator<Map.Entry<String, String>> iterator =
-                  rb.req.getCore().getCancellableQueryTracker().getActiveQueriesGenerated();
-
-              while (iterator.hasNext()) {
-                Map.Entry<String, String> entry = iterator.next();
-                ew.put(entry.getKey(), entry.getValue());
-              }
-            });
-  }
-
-  @Override
-  @SuppressWarnings("unchecked")
-  public void handleResponses(ResponseBuilder rb, ShardRequest sreq) {
-    if (!shouldProcess) {
-      return;
-    }
-
-    NamedList<String> resultList = new NamedList<>();
-
-    for (ShardResponse r : sreq.responses) {
-
-      if (rb.getTaskStatusCheckUUID() != null) {
-        boolean isTaskActiveOnShard = r.getSolrResponse().getResponse().getBooleanArg("taskStatus");
-
-        if (isTaskActiveOnShard) {
-          rb.rsp
-              .getValues()
-              .add("taskStatus", "id:" + rb.getTaskStatusCheckUUID() + ", status: active");
-          return;
-        } else {
-          continue;
-        }
-      }
-
-      LinkedHashMap<String, String> result =
-          (LinkedHashMap<String, String>) r.getSolrResponse().getResponse().get("taskList");
-
-      Iterator<Map.Entry<String, String>> iterator = result.entrySet().iterator();
-
-      while (iterator.hasNext()) {
-        Map.Entry<String, String> entry = iterator.next();
-
-        resultList.add(entry.getKey(), entry.getValue());
-      }
-    }
-
-    if (rb.getTaskStatusCheckUUID() != null) {
-      // We got here with the specific taskID check being specified -- this means that the taskID
-      // was not found in active tasks on any shard
-      rb.rsp
-          .getValues()
-          .add("taskStatus", "id:" + rb.getTaskStatusCheckUUID() + ", status: inactive");
-      return;
-    }
-
-    rb.rsp.getValues().add("taskList", resultList);
-  }
-
-  @Override
-  public String getDescription() {
-    return "Responsible for listing all active cancellable tasks and also supports checking the status of "
-        + "a particular task";
-  }
-
-  @Override
-  public Category getCategory() {
-    return Category.OTHER;
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java b/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java
index f1ce12cd937..810e66d8957 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/ActiveTasksListHandler.java
@@ -19,49 +19,57 @@ package org.apache.solr.handler.component;
 import static org.apache.solr.common.params.CommonParams.TASK_CHECK_UUID;
 
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-import org.apache.solr.api.AnnotatedApi;
 import org.apache.solr.api.Api;
-import org.apache.solr.handler.admin.api.ListActiveTasksAPI;
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.client.api.model.ActiveTaskDetails;
+import org.apache.solr.common.params.ShardParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.handler.admin.api.ActiveTask;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestHandler;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.security.AuthorizationContext;
 import org.apache.solr.security.PermissionNameProvider;
 
-/** Handles request for listing all active cancellable tasks */
+/** Handles request for listing all active cancellable tasks and get status check of any taskId. */
 public class ActiveTasksListHandler extends TaskManagementHandler {
   // This can be a parent level member but we keep it here to allow future handlers to have
   // a custom list of components
-  private List<SearchComponent> components;
 
   @Override
   public void handleRequestBody(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    Map<String, String> extraParams = null;
-    ResponseBuilder rb = buildResponseBuilder(req, rsp, getComponentsList());
-
-    rb.setIsTaskListRequest(true);
-
-    String taskStatusCheckUUID = req.getParams().get(TASK_CHECK_UUID, null);
-
-    if (taskStatusCheckUUID != null) {
-      if (rb.isDistrib) {
-        extraParams = new HashMap<>();
-
-        extraParams.put(TASK_CHECK_UUID, taskStatusCheckUUID);
+    String taskStatusCheckID = req.getParams().get(TASK_CHECK_UUID, null);
+    boolean isShardedRequest = req.getParams().getBool(ShardParams.IS_SHARD, false);
+
+    if (taskStatusCheckID != null) {
+      boolean taskStatus = ActiveTaskQuerySupport.isTaskActive(req, taskStatusCheckID);
+      if (isShardedRequest) {
+        rsp.add("taskStatus", taskStatus);
+      } else {
+        rsp.add(
+            "taskStatus",
+            "id: " + taskStatusCheckID + ", status: " + (taskStatus ? "active" : "inactive"));
       }
 
-      rb.setTaskStatusCheckUUID(taskStatusCheckUUID);
+    } else {
+      NamedList<String> tasks = new SimpleOrderedMap<>();
+      List<ActiveTaskDetails> taskList = ActiveTaskQuerySupport.listActiveTasks(req);
+      if (taskList != null) {
+        for (ActiveTaskDetails task : taskList) {
+          tasks.add(task.id, task.query);
+        }
+      }
+      rsp.add("taskList", tasks);
     }
-
-    processRequest(req, rb, extraParams);
   }
 
+  // ////////////////////// SolrInfoMBeans methods //////////////////////
+
   @Override
   public String getDescription() {
-    return "activetaskslist";
+    return "Active Tasks List";
   }
 
   @Override
@@ -79,7 +87,6 @@ public class ActiveTasksListHandler extends TaskManagementHandler {
     if (path.startsWith("/tasks/list")) {
       return this;
     }
-
     return null;
   }
 
@@ -90,14 +97,11 @@ public class ActiveTasksListHandler extends TaskManagementHandler {
 
   @Override
   public Collection<Api> getApis() {
-    return AnnotatedApi.getApis(new ListActiveTasksAPI(this));
+    return List.of();
   }
 
-  private List<SearchComponent> getComponentsList() {
-    if (components == null) {
-      components = buildComponentsList();
-    }
-
-    return components;
+  @Override
+  public Collection<Class<? extends JerseyResource>> getJerseyResources() {
+    return List.of(ActiveTask.class);
   }
 }
diff --git a/solr/core/src/java/org/apache/solr/handler/component/TaskManagementHandler.java b/solr/core/src/java/org/apache/solr/handler/component/TaskManagementHandler.java
index afb7a05c586..3e9c5ec2116 100644
--- a/solr/core/src/java/org/apache/solr/handler/component/TaskManagementHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/component/TaskManagementHandler.java
@@ -115,9 +115,6 @@ public abstract class TaskManagementHandler extends RequestHandlerBase
     QueryCancellationComponent component = new QueryCancellationComponent();
     components.add(component);
 
-    ActiveTasksListComponent activeTasksListComponent = new ActiveTasksListComponent();
-    components.add(activeTasksListComponent);
-
     return components;
   }
 
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.java
new file mode 100644
index 00000000000..1ab1e2bc489
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/ActiveTaskTest.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.api.model.ListActiveTaskResponse;
+import org.apache.solr.client.api.model.TaskStatusResponse;
+import org.apache.solr.core.CancellableQueryTracker;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.request.SolrQueryRequest;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class ActiveTaskTest extends SolrTestCaseJ4 {
+
+  private SolrQueryRequest mockQueryRequest;
+  private SolrCore solrCore;
+  private CancellableQueryTracker cancellableQueryTracker;
+
+  private ActiveTask activeTask;
+
+  @BeforeClass
+  public static void ensureWorkingMockito() {
+    assumeWorkingMockito();
+  }
+
+  @Override
+  @Before
+  public void setUp() throws Exception {
+    super.setUp();
+
+    mockQueryRequest = mock(SolrQueryRequest.class);
+    solrCore = mock(SolrCore.class);
+    cancellableQueryTracker = mock(CancellableQueryTracker.class);
+
+    activeTask = new ActiveTask(mockQueryRequest);
+  }
+
+  @Test
+  public void testGetActiveTasks() throws Exception {
+
+    Map<String, String> myMap = new LinkedHashMap<>();
+    myMap.put("taskID1", "/search?q=h&gf=text-1");
+    myMap.put("taskID2", "/search?q=h&gf=text-2");
+    Iterator<Map.Entry<String, String>> mockIterator = myMap.entrySet().iterator();
+
+    when(mockQueryRequest.getCore()).thenReturn(solrCore);
+    when(solrCore.getCancellableQueryTracker()).thenReturn(cancellableQueryTracker);
+    when(cancellableQueryTracker.getActiveQueriesGenerated()).thenReturn(mockIterator);
+
+    ListActiveTaskResponse response = activeTask.listAllActiveTasks();
+    assertNotNull(response.tasks);
+
+    assertEquals(2, response.tasks.size());
+
+    assertEquals("taskID1", response.tasks.get(0).id);
+    assertEquals("/search?q=h&gf=text-1", response.tasks.get(0).query);
+
+    assertNull(response.error);
+  }
+
+  @Test
+  public void testGetTaskStatus() throws Exception {
+
+    when(mockQueryRequest.getCore()).thenReturn(solrCore);
+    when(solrCore.getCancellableQueryTracker()).thenReturn(cancellableQueryTracker);
+    when(cancellableQueryTracker.isQueryIdActive("taskID_running")).thenReturn(true);
+    when(cancellableQueryTracker.isQueryIdActive("taskID_stopped")).thenReturn(false);
+
+    TaskStatusResponse responseRunningTask = activeTask.getTaskStatus("taskID_running");
+    assertEquals(TaskStatusResponse.TaskStatus.ACTIVE, responseRunningTask.status);
+    assertNull(responseRunningTask.error);
+
+    TaskStatusResponse responseStoppedTask = activeTask.getTaskStatus("taskID_stopped");
+    assertEquals(TaskStatusResponse.TaskStatus.INACTIVE, responseStoppedTask.status);
+    assertNull(responseStoppedTask.error);
+  }
+}
diff --git a/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java b/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java
index 13c98d87ace..f1039705765 100644
--- a/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java
+++ b/solr/core/src/test/org/apache/solr/search/TestTaskManagement.java
@@ -33,15 +33,23 @@ import org.apache.lucene.util.BytesRef;
 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.jetty.HttpJettySolrClient;
 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.cloud.SolrCloudTestCase;
 import org.apache.solr.common.SolrInputDocument;
+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.CommonParams;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.ExecutorUtil;
 import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.embedded.JettySolrRunner;
+import org.apache.solr.request.SolrQueryRequestBase;
 import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
 import org.junit.After;
@@ -213,6 +221,114 @@ public class TestTaskManagement extends SolrCloudTestCase {
     assertTrue(result.contains("inactive"));
   }
 
+  @Test
+  public void testCheckSpecificQueryStatus_Active() throws Exception {
+    for (int i = 0; i < 10; i++) {
+      executeQueryAsync(Integer.toString(i));
+    }
+
+    ModifiableSolrParams params = new ModifiableSolrParams();
+    params.set("taskUUID", "5");
+
+    var request =
+        new GenericSolrRequest(
+                SolrRequest.METHOD.GET, "/tasks/list", SolrRequest.SolrRequestType.ADMIN, params)
+            .setRequiresCollection(true);
+    NamedList<Object> queryResponse = cluster.getSolrClient(COLLECTION_NAME).request(request);
+
+    String result = (String) queryResponse.get("taskStatus");
+
+    assertTrue(result.contains("active"));
+  }
+
+  @Test
+  public void testCheckSpecificQueryStatus_Inactive() throws Exception {
+    for (int i = 0; i < 10; i++) {
+      executeQueryAsync(Integer.toString(i));
+    }
+
+    ModifiableSolrParams params = new ModifiableSolrParams();
+    params.set("taskUUID", "15");
+
+    var request =
+        new GenericSolrRequest(
+                SolrRequest.METHOD.GET, "/tasks/list", SolrRequest.SolrRequestType.ADMIN, params)
+            .setRequiresCollection(true);
+    NamedList<Object> queryResponse = cluster.getSolrClient(COLLECTION_NAME).request(request);
+
+    String result = (String) queryResponse.get("taskStatus");
+
+    assertTrue(result.contains("inactive"));
+  }
+
+  /**
+   * Regression test for cross-shard task visibility.
+   *
+   * <p>On {@code main}, {@code ActiveTasksListHandler.handleRequestBody()} delegates to {@code
+   * processRequest()}, which fans the request out to every shard via the distributed query
+   * pipeline. {@code ActiveTasksListComponent.handleResponses()} then aggregates the per-shard
+   * results, so a task running on shard 2 is visible when the status-check request lands on shard
+   * 1.
+   *
+   * <p>If this handler is migrated to JAX-RS and the fan-out is replaced with a direct call to the
+   * handler node's own {@code CancellableQueryTracker}, a task registered only on shard 2 becomes
+   * invisible to a request handled by shard 1, causing a false "inactive" response.
+   */
+  @Test
+  public void testCrossShardTaskStatusVisibility() throws Exception {
+    DocCollection docCollection =
+        cluster.getSolrClient().getClusterState().getCollection(COLLECTION_NAME);
+    List<Slice> slices = new ArrayList<>(docCollection.getSlices());
+    assertEquals("test requires exactly 2 shards", 2, slices.size());
+    Replica shard1Leader = slices.get(0).getLeader();
+    Replica shard2Leader = slices.get(1).getLeader();
+    assumeFalse(
+        "Both shard leaders landed on the same node — cross-shard scenario cannot be tested",
+        shard1Leader.getNodeName().equals(shard2Leader.getNodeName()));
+
+    final String taskId = "cross-shard-visibility-test";
+
+    JettySolrRunner shard2Jetty =
+        cluster.getJettySolrRunners().stream()
+            .filter(j -> j.getNodeName().equals(shard2Leader.getNodeName()))
+            .findFirst()
+            .orElseThrow(() -> new AssertionError("No Jetty found for shard 2 leader"));
+    try (SolrCore shard2Core = shard2Jetty.getCoreContainer().getCore(shard2Leader.getCoreName())) {
+      assertNotNull("Could not open shard 2 core", shard2Core);
+      ModifiableSolrParams fakeParams = new ModifiableSolrParams();
+      fakeParams.set(CommonParams.QUERY_UUID, taskId);
+      try (var fakeReq = new SolrQueryRequestBase(shard2Core, fakeParams)) {
+        shard2Core.getCancellableQueryTracker().generateQueryID(fakeReq);
+      }
+
+      try {
+        try (var shard1Client =
+            new HttpJettySolrClient.Builder(shard1Leader.getBaseUrl()).build()) {
+          ModifiableSolrParams params = new ModifiableSolrParams();
+          params.set(CommonParams.TASK_CHECK_UUID, taskId);
+          var statusReq =
+              new GenericSolrRequest(
+                      SolrRequest.METHOD.GET, "/tasks/list", SolrRequestType.ADMIN, params)
+                  .setRequiresCollection(true);
+          NamedList<Object> response = shard1Client.request(statusReq, COLLECTION_NAME);
+
+          Object taskStatus = response.get("taskStatus");
+          assertNotNull("taskStatus missing from response", taskStatus);
+          assertTrue(
+              "Task registered on shard 2 must be visible from shard 1 via cross-shard fan-out. "
+                  + "Got: "
+                  + taskStatus
+                  + " ("
+                  + taskStatus.getClass().getSimpleName()
+                  + ") — if this is Boolean.FALSE the distributed aggregation was dropped.",
+              taskStatus instanceof String && ((String) taskStatus).contains("status: active"));
+        }
+      } finally {
+        shard2Core.getCancellableQueryTracker().releaseQueryID(taskId);
+      }
+    }
+  }
+
   private CompletableFuture<Void> cancelQuery(
       final String queryID, Set<Integer> cancelledQueryIdsSet, Set<Integer> notFoundQueryIdSet) {
     return CompletableFuture.runAsync(
diff --git a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc
index a320d9cfdf3..5cce6eb8bc9 100644
--- a/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc
+++ b/solr/solr-ref-guide/modules/deployment-guide/pages/task-management.adoc
@@ -57,13 +57,20 @@ V2 API::
 ====
 [source,bash]
 ----
-curl -X GET "http://localhost:8983/v2/collections/collectionName/tasks/list"
+curl -X GET "http://localhost:8983/v2/collections/collectionName/tasks"
 ----
 ====
 ======
 
 === Sample Response
 
+The V1 and V2 APIs currently return `taskList` in different shapes.
+
+[tabs#listalltasks-response]
+======
+V1 API::
++
+====
 ----
 {
   "responseHeader":{
@@ -74,6 +81,30 @@ curl -X GET "http://localhost:8983/v2/collections/collectionName/tasks/list"
     "5","q=weight_i:[0+TO+200]&canCancel=true&queryUUID=5",
     "4bcd27bb-0792-4512-a699-532fa7878bd3","q=weight_i:[0+TO+200]&canCancel=true"]}
 ----
+====
+
+V2 API::
++
+====
+[source,json]
+----
+{
+  "responseHeader":{
+    "status":0,
+    "QTime":16},
+  "tasks":[
+    {
+      "id":"0",
+      "query":"q=weight_i:[0+TO+200]&canCancel=true&queryUUID=0"},
+    {
+      "id":"5",
+      "query":"q=weight_i:[0+TO+200]&canCancel=true&queryUUID=5"},
+    {
+      "id":"4bcd27bb-0792-4512-a699-532fa7878bd3",
+      "query":"q=weight_i:[0+TO+200]&canCancel=true"}]}
+----
+====
+======
 
 == Cancelling An Active Cancellable Task
 To cancel an active task, please use the following syntax:
@@ -140,20 +171,43 @@ V2 API::
 ====
 [source,bash]
 ----
-curl -X GET "http://localhost:8983/v2/collections/collectionName/tasks/list?taskUUID=5"
+curl -X GET "http://localhost:8983/v2/collections/collectionName/tasks/5"
 ----
 ====
 ======
 
 === taskUUID Parameter
-`taskUUID` parameter can be used to specify a task UUID whose status can be checked.
+With the V1 API, the `taskUUID` request parameter is used to specify a task UUID whose status can be checked.
+With the V2 API, the task ID is instead supplied as part of the path, e.g. `/v2/collections/collectionName/tasks/{taskID}`.
 
 === Sample Response
 
+The V1 and V2 APIs currently return `taskStatus` in different shapes.
+
+[tabs#checksingletask-response]
+======
+V1 API::
++
+====
+----
+{
+  "responseHeader":{
+    "status":0,
+    "QTime":16},
+  "taskStatus":"id: 5, status: active"}
+----
+====
+
+V2 API::
++
+====
+[source,json]
 ----
 {
   "responseHeader":{
     "status":0,
     "QTime":16},
-  "taskStatus":"id:5, status: active"}
+  "status":"ACTIVE"}
 ----
+====
+======


(solr) 06/06: Remove dead classes BaseHandlerApiSupport and PrintWriterWrapper (#4654)

Posted by ds...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e76c7588624c5f84d1da1bfb04daefc4d6b81bae
Author: Pierre Salagnac <ps...@apache.org>
AuthorDate: Mon Jul 27 14:16:03 2026 +0200

    Remove dead classes BaseHandlerApiSupport and PrintWriterWrapper (#4654)
    
    (cherry picked from commit 63b3d6bf12015e73c1ddda096a1c864af4a3dcb8)
---
 .../solr/handler/admin/BaseHandlerApiSupport.java  | 236 ---------------------
 .../apache/solr/security/PrintWriterWrapper.java   | 211 ------------------
 2 files changed, 447 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/handler/admin/BaseHandlerApiSupport.java b/solr/core/src/java/org/apache/solr/handler/admin/BaseHandlerApiSupport.java
deleted file mode 100644
index 82d2e869aad..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/BaseHandlerApiSupport.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.POST;
-import static org.apache.solr.common.SolrException.ErrorCode.BAD_REQUEST;
-import static org.apache.solr.common.util.StrUtils.splitSmart;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.stream.Collectors;
-import org.apache.solr.api.Api;
-import org.apache.solr.api.ApiSupport;
-import org.apache.solr.client.solrj.SolrRequest;
-import org.apache.solr.client.solrj.request.ApiMapping.CommandMeta;
-import org.apache.solr.client.solrj.request.ApiMapping.V2EndPoint;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.common.util.CommandOperation;
-import org.apache.solr.common.util.SuppressForbidden;
-import org.apache.solr.common.util.Utils;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-
-/**
- * This is a utility class to provide an easy mapping of request handlers which support multiple
- * commands to the V2 API format (core admin api, collections api). This helps in automatically
- * mapping paths to actions and old parameter names to new parameter names
- */
-public abstract class BaseHandlerApiSupport implements ApiSupport {
-  protected final Map<SolrRequest.METHOD, Map<V2EndPoint, List<ApiCommand>>> commandsMapping;
-
-  protected BaseHandlerApiSupport() {
-    commandsMapping = new HashMap<>();
-    for (ApiCommand cmd : getCommands()) {
-      Map<V2EndPoint, List<ApiCommand>> m = commandsMapping.get(cmd.meta().getHttpMethod());
-      if (m == null) commandsMapping.put(cmd.meta().getHttpMethod(), m = new HashMap<>());
-      List<ApiCommand> list = m.get(cmd.meta().getEndPoint());
-      if (list == null) m.put(cmd.meta().getEndPoint(), list = new ArrayList<>());
-      list.add(cmd);
-    }
-  }
-
-  @Override
-  public synchronized Collection<Api> getApis() {
-    return getEndPoints().stream().map(this::getApi).collect(Collectors.toUnmodifiableList());
-  }
-
-  private Api getApi(final V2EndPoint op) {
-    final BaseHandlerApiSupport apiHandler = this;
-    return new Api(Utils.getSpec(op.getSpecName())) {
-      @Override
-      public void call(SolrQueryRequest req, SolrQueryResponse rsp) {
-        SolrParams params = req.getParams();
-        SolrRequest.METHOD method = SolrRequest.METHOD.valueOf(req.getHttpMethod());
-        List<ApiCommand> commands = commandsMapping.get(method).get(op);
-        try {
-          if (method == POST) {
-            List<CommandOperation> cmds = req.getCommands(true);
-            if (cmds.size() > 1)
-              throw new SolrException(BAD_REQUEST, "Only one command is allowed");
-            CommandOperation c = cmds.size() == 0 ? null : cmds.get(0);
-            ApiCommand command = null;
-            String commandName = c == null ? null : c.name;
-            for (ApiCommand cmd : commands) {
-              if (Objects.equals(cmd.meta().getName(), commandName)) {
-                command = cmd;
-                break;
-              }
-            }
-
-            if (command == null) {
-              throw new SolrException(BAD_REQUEST, " no such command " + c);
-            }
-            wrapParams(req, c, command, false);
-            command.invoke(req, rsp, apiHandler);
-
-          } else {
-            if (commands == null || commands.isEmpty()) {
-              rsp.add("error", "No support for : " + method + " at :" + req.getPath());
-              return;
-            }
-            if (commands.size() > 1) {
-              for (ApiCommand command : commands) {
-                if (command.meta().getName().equals(req.getPath())) {
-                  commands = List.of(command);
-                  break;
-                }
-              }
-            }
-            wrapParams(req, new CommandOperation("", Map.of()), commands.get(0), true);
-            commands.get(0).invoke(req, rsp, apiHandler);
-          }
-
-        } catch (SolrException e) {
-          throw e;
-        } catch (Exception e) {
-          // TODO BAD_REQUEST is a wild guess; should we flip the default?  fail here to investigate
-          // how this happens in tests
-          throw new SolrException(BAD_REQUEST, e);
-        } finally {
-          req.setParams(params);
-        }
-      }
-    };
-  }
-
-  /** Wrapper for SolrParams that wraps V2 params and exposes them as V1 params. */
-  @SuppressForbidden(
-      reason = "CommandOperation.getCommandData can return null when there is no payload")
-  private static void wrapParams(
-      final SolrQueryRequest req,
-      final CommandOperation co,
-      final ApiCommand cmd,
-      final boolean useRequestParams) {
-    final Map<String, String> pathValues = req.getPathTemplateValues();
-    final Map<String, Object> map =
-        co == null || !(co.getCommandData() instanceof Map)
-            ? Collections.singletonMap("", co.getCommandData())
-            : co.getDataMap();
-    final SolrParams origParams = req.getParams();
-
-    req.setParams(
-        new SolrParams() {
-          @Override
-          public String get(String param) {
-            Object vals = getParams0(param);
-            if (vals == null) return null;
-            if (vals instanceof String) return (String) vals;
-            if (vals instanceof Boolean || vals instanceof Number) return String.valueOf(vals);
-            if (vals instanceof String[] && ((String[]) vals).length > 0)
-              return ((String[]) vals)[0];
-            return null;
-          }
-
-          private Object getParams0(String param) {
-            param = cmd.meta().getParamSubstitute(param); // v1 -> v2, possibly dotted path
-            Object o =
-                param.indexOf('.') > 0
-                    ? Utils.getObjectByPath(map, true, splitSmart(param, '.'))
-                    : map.get(param);
-            if (o == null) o = pathValues.get(param);
-            if (o == null && useRequestParams) o = origParams.getParams(param);
-            if (o instanceof List) {
-              @SuppressWarnings("unchecked")
-              List<String> l = (List<String>) o;
-              return l.toArray(new String[0]);
-            }
-
-            return o;
-          }
-
-          @Override
-          public String[] getParams(String param) {
-            Object vals = getParams0(param);
-            return vals == null || vals instanceof String[]
-                ? (String[]) vals
-                : new String[] {vals.toString()};
-          }
-
-          @Override
-          public Iterator<String> getParameterNamesIterator() {
-            return cmd.meta().getParamNamesIterator(co);
-          }
-
-          @Override
-          public void writeMap(EntryWriter ew) throws IOException {
-            for (Iterator<String> it = getParameterNamesIterator(); it.hasNext(); ) {
-              final String param = it.next();
-              String key = cmd.meta().getParamSubstitute(param);
-              Object o =
-                  key.indexOf('.') > 0
-                      ? Utils.getObjectByPath(map, true, splitSmart(key, '.'))
-                      : map.get(key);
-              if (o == null) o = pathValues.get(key);
-              if (o == null && useRequestParams) o = origParams.getParams(key);
-              if (o == null) continue;
-              // make strings out of as many things as we can now to minimize differences from
-              // the standard impls that pass through a NamedList/SimpleOrderedMap...
-              Class<?> oClass = o.getClass();
-              if (oClass.isPrimitive()
-                  || Number.class.isAssignableFrom(oClass)
-                  || Character.class.isAssignableFrom(oClass)
-                  || Boolean.class.isAssignableFrom(oClass)) {
-                ew.put(param, String.valueOf(o));
-              } else if (List.class.isAssignableFrom(oClass)) {
-                @SuppressWarnings({"unchecked"})
-                List<?> l = (List<?>) o;
-                if (l.isEmpty() || l.get(0) instanceof String) {
-                  ew.put(param, l.toArray(new String[0]));
-                } else {
-                  ew.put(param, o);
-                }
-              } else {
-                // Lists pass through but will require special handling downstream
-                // if they contain non-string elements.
-                ew.put(param, o);
-              }
-            }
-          }
-        });
-  }
-
-  protected abstract Collection<ApiCommand> getCommands();
-
-  protected abstract Collection<V2EndPoint> getEndPoints();
-
-  public interface ApiCommand {
-    CommandMeta meta();
-
-    void invoke(SolrQueryRequest req, SolrQueryResponse rsp, BaseHandlerApiSupport apiHandler)
-        throws Exception;
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/security/PrintWriterWrapper.java b/solr/core/src/java/org/apache/solr/security/PrintWriterWrapper.java
deleted file mode 100644
index 532a828e384..00000000000
--- a/solr/core/src/java/org/apache/solr/security/PrintWriterWrapper.java
+++ /dev/null
@@ -1,211 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.solr.security;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.Locale;
-
-/** Wrapper for PrintWriter that delegates to constructor arg */
-public class PrintWriterWrapper extends PrintWriter {
-  private PrintWriter printWriter;
-
-  public PrintWriterWrapper(PrintWriter printWriter) {
-    super(new StringWriter());
-    this.printWriter = printWriter;
-  }
-
-  @Override
-  public PrintWriter append(char c) {
-    return printWriter.append(c);
-  }
-
-  @Override
-  public PrintWriter append(CharSequence csq) {
-    return printWriter.append(csq);
-  }
-
-  @Override
-  public PrintWriter append(CharSequence csq, int start, int end) {
-    return printWriter.append(csq, start, end);
-  }
-
-  @Override
-  public boolean checkError() {
-    return printWriter.checkError();
-  }
-
-  @Override
-  protected void clearError() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void close() {
-    printWriter.close();
-  }
-
-  @Override
-  public void flush() {
-    printWriter.flush();
-  }
-
-  @Override
-  public PrintWriter format(Locale l, String format, Object... args) {
-    return printWriter.format(l, format, args);
-  }
-
-  @Override
-  public PrintWriter format(String format, Object... args) {
-    throw new UnsupportedOperationException("Forbidden API");
-  }
-
-  @Override
-  public void print(boolean b) {
-    printWriter.print(b);
-  }
-
-  @Override
-  public void print(char c) {
-    printWriter.print(c);
-  }
-
-  @Override
-  public void print(char[] s) {
-    printWriter.print(s);
-  }
-
-  @Override
-  public void print(double d) {
-    printWriter.print(d);
-  }
-
-  @Override
-  public void print(float f) {
-    printWriter.print(f);
-  }
-
-  @Override
-  public void print(int i) {
-    printWriter.print(i);
-  }
-
-  @Override
-  public void print(long l) {
-    printWriter.print(l);
-  }
-
-  @Override
-  public void print(Object obj) {
-    printWriter.print(obj);
-  }
-
-  @Override
-  public void print(String s) {
-    printWriter.print(s);
-  }
-
-  @Override
-  public PrintWriter printf(Locale l, String format, Object... args) {
-    return printWriter.printf(l, format, args);
-  }
-
-  @Override
-  public PrintWriter printf(String format, Object... args) {
-    throw new UnsupportedOperationException("Forbidden API");
-  }
-
-  @Override
-  public void println() {
-    printWriter.println();
-  }
-
-  @Override
-  public void println(boolean x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  public void println(char x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  public void println(char[] x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  public void println(double x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  public void println(float x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  public void println(int x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  public void println(long x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  public void println(Object x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  public void println(String x) {
-    printWriter.println(x);
-  }
-
-  @Override
-  protected void setError() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public void write(char[] buf) {
-    printWriter.write(buf);
-  }
-
-  @Override
-  public void write(char[] buf, int off, int len) {
-    printWriter.write(buf, off, len);
-  }
-
-  @Override
-  public void write(int c) {
-    printWriter.write(c);
-  }
-
-  @Override
-  public void write(String s) {
-    printWriter.write(s);
-  }
-
-  @Override
-  public void write(String s, int off, int len) {
-    printWriter.write(s, off, len);
-  }
-}