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

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


The following commit(s) were added to refs/heads/main by this push:
     new 597ed677408 SOLR-16396 | Migrate GET /config/overlay and GET 
/config/znodeVersion to JAX-RS. (#5022)
597ed677408 is described below

commit 597ed67740831566b708b793f52554b2e49e7e17
Author: Jalaz Kumar <[email protected]>
AuthorDate: Mon Oct 12 17:46:01 2026 +0530

    SOLR-16396 | Migrate GET /config/overlay and GET /config/znodeVersion to 
JAX-RS. (#5022)
---
 .../unreleased/SOLR-16396-config-get-others.yml    |   9 ++
 .../apache/solr/client/api/endpoint/ConfigApi.java |  26 +++++
 .../client/api/model/ConfigOverlayResponse.java    |  25 +++++
 .../api/model/ConfigZnodeVersionResponse.java      |  32 ++++++
 .../org/apache/solr/handler/SolrConfigHandler.java | 122 ++++++++++-----------
 .../apache/solr/handler/admin/api/GetConfig.java   |  29 +++++
 .../solr/handler/admin/api/GetConfigAPI.java       |   2 -
 .../solr/handler/admin/V2ConfigAPIMappingTest.java |   2 -
 .../handler/admin/api/GetConfigSolrCloudTest.java  |  26 ++++-
 .../solr/handler/admin/api/GetConfigTest.java      |  24 ++++
 .../solrj/src/resources/java-template/api.mustache |   8 +-
 11 files changed, 234 insertions(+), 71 deletions(-)

diff --git a/changelog/unreleased/SOLR-16396-config-get-others.yml 
b/changelog/unreleased/SOLR-16396-config-get-others.yml
new file mode 100644
index 00000000000..56e36c32586
--- /dev/null
+++ b/changelog/unreleased/SOLR-16396-config-get-others.yml
@@ -0,0 +1,9 @@
+title:
+  Migrate GET /config/overlay and GET /config/znodeVersion to JAX-RS.
+type: changed
+authors:
+  - name: Jalaz Kumar
+    nick: jaykay12
+links:
+  - name: SOLR-16396
+    url: https://issues.apache.org/jira/browse/SOLR-16396
diff --git 
a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java 
b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java
index 3e0ab463af2..cc9cecc1bb5 100644
--- a/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/ConfigApi.java
@@ -25,6 +25,8 @@ import jakarta.ws.rs.GET;
 import jakarta.ws.rs.Path;
 import jakarta.ws.rs.QueryParam;
 import org.apache.solr.client.api.model.ConfigInfoResponse;
+import org.apache.solr.client.api.model.ConfigOverlayResponse;
+import org.apache.solr.client.api.model.ConfigZnodeVersionResponse;
 import org.apache.solr.client.api.util.StoreApiParameters;
 
 /** V2 API for reading and modifying a core/collection's config */
@@ -42,5 +44,29 @@ public interface ConfigApi {
             @DefaultValue("false")
             @Parameter(description = "Expand request handler useParams and 
effective parameters")
             boolean expandParams);
+
+    @GET
+    @Path("/overlay")
+    @StoreApiParameters
+    @Operation(
+        summary = "Fetch the config overlay of the specified core or 
collection",
+        tags = {"config"})
+    ConfigOverlayResponse getOverlay();
+
+    @GET
+    @Path("/znodeVersion")
+    @StoreApiParameters
+    @Operation(
+        summary = "Fetch znode versions for config overlay and request params",
+        tags = {"config"})
+    ConfigZnodeVersionResponse getZnodeVersion(
+        @QueryParam("overlay")
+            @DefaultValue("-1")
+            @Parameter(description = "Expected overlay znode version")
+            int expectedOverlayVersion,
+        @QueryParam("params")
+            @DefaultValue("-1")
+            @Parameter(description = "Expected request-params znode version")
+            int expectedParamsVersion);
   }
 }
diff --git 
a/solr/api/src/java/org/apache/solr/client/api/model/ConfigOverlayResponse.java 
b/solr/api/src/java/org/apache/solr/client/api/model/ConfigOverlayResponse.java
new file mode 100644
index 00000000000..e75aaf25fba
--- /dev/null
+++ 
b/solr/api/src/java/org/apache/solr/client/api/model/ConfigOverlayResponse.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.Map;
+
+public class ConfigOverlayResponse extends SolrJerseyResponse {
+  @JsonProperty("overlay")
+  public Map<String, Object> overlay;
+}
diff --git 
a/solr/api/src/java/org/apache/solr/client/api/model/ConfigZnodeVersionResponse.java
 
b/solr/api/src/java/org/apache/solr/client/api/model/ConfigZnodeVersionResponse.java
new file mode 100644
index 00000000000..01cecfaa73f
--- /dev/null
+++ 
b/solr/api/src/java/org/apache/solr/client/api/model/ConfigZnodeVersionResponse.java
@@ -0,0 +1,32 @@
+/*
+ * 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 ConfigZnodeVersionResponse extends SolrJerseyResponse {
+  @JsonProperty("znodeVersion")
+  public ZnodeVersions znodeVersion;
+
+  public static class ZnodeVersions {
+    @JsonProperty("overlay")
+    public int overlay;
+
+    @JsonProperty("params")
+    public int params;
+  }
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java 
b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
index d943272657f..d61b7d2bacb 100644
--- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
@@ -174,7 +174,7 @@ public class SolrConfigHandler extends RequestHandlerBase
     return immutable != null && Boolean.parseBoolean(immutable.toString());
   }
 
-  private class Command {
+  private static class Command {
     private final SolrQueryRequest req;
     private final SolrQueryResponse resp;
     private final String method;
@@ -202,7 +202,7 @@ public class SolrConfigHandler extends RequestHandlerBase
             resp, new 
GetConfig(req).getConfig(req.getParams().getBool("expandParams", false)));
       } else {
         if (ConfigOverlay.NAME.equals(parts.get(1))) {
-          resp.add(ConfigOverlay.NAME, 
req.getCore().getSolrConfig().getOverlay());
+          V2ApiUtils.squashIntoSolrResponseWithoutHeader(resp, new 
GetConfig(req).getOverlay());
         } else if (RequestParams.NAME.equals(parts.get(1))) {
           if (parts.size() == 3) {
             RequestParams params = 
req.getCore().getSolrConfig().getRequestParams();
@@ -219,66 +219,12 @@ public class SolrConfigHandler extends RequestHandlerBase
 
         } else {
           if (ZNODEVER.equals(parts.get(1))) {
-            resp.add(
-                ZNODEVER,
-                Map.of(
-                    ConfigOverlay.NAME,
-                    req.getCore().getSolrConfig().getOverlay().getVersion(),
-                    RequestParams.NAME,
-                    
req.getCore().getSolrConfig().getRequestParams().getZnodeVersion()));
-            boolean isStale = false;
-            int expectedVersion = req.getParams().getInt(ConfigOverlay.NAME, 
-1);
-            int actualVersion = 
req.getCore().getSolrConfig().getOverlay().getVersion();
-            if (expectedVersion > actualVersion) {
-              log.info(
-                  "expecting overlay version {} but my version is {}",
-                  expectedVersion,
-                  actualVersion);
-              isStale = true;
-            } else if (expectedVersion != -1) {
-              log.info("I already have the expected version {} of config", 
expectedVersion);
-            }
-            expectedVersion = req.getParams().getInt(RequestParams.NAME, -1);
-            actualVersion = 
req.getCore().getSolrConfig().getRequestParams().getZnodeVersion();
-            if (expectedVersion > actualVersion) {
-              log.info(
-                  "expecting params version {} but my version is {}",
-                  expectedVersion,
-                  actualVersion);
-              isStale = true;
-            } else if (expectedVersion != -1) {
-              log.info("I already have the expected version {} of params", 
expectedVersion);
-            }
-            if (isStale && req.getCore().getResourceLoader() instanceof 
ZkSolrResourceLoader) {
-              new Thread(
-                      () -> {
-                        if (!reloadLock.tryLock()) {
-                          log.info("Another reload is in progress . Not doing 
anything");
-                          return;
-                        }
-                        try {
-                          log.info("Trying to update my configs");
-                          SolrCore.getConfListener(
-                                  req.getCore(),
-                                  (ZkSolrResourceLoader) 
req.getCore().getResourceLoader())
-                              .run();
-                        } catch (Exception e) {
-                          log.error("Unable to refresh conf ", e);
-                        } finally {
-                          reloadLock.unlock();
-                        }
-                      },
-                      SolrConfigHandler.class.getSimpleName() + "-refreshconf")
-                  .start();
-            } else {
-              if (log.isInfoEnabled()) {
-                log.info(
-                    "isStale {} , resourceloader {}",
-                    isStale,
-                    req.getCore().getResourceLoader().getClass().getName());
-              }
-            }
-
+            V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                resp,
+                new GetConfig(req)
+                    .getZnodeVersion(
+                        req.getParams().getInt(ConfigOverlay.NAME, -1),
+                        req.getParams().getInt(RequestParams.NAME, -1)));
           } else {
             Map<String, Object> m = getConfigDetails(parts.get(1), req);
             Map<String, Object> val = new LinkedHashMap<>();
@@ -970,6 +916,58 @@ public class SolrConfigHandler extends RequestHandlerBase
     return activeReplicas;
   }
 
+  public static void maybeRefreshStaleConfig(
+      SolrCore core, int expectedOverlayVersion, int expectedParamsVersion) {
+    boolean isStale =
+        isExpectedVersionStale(
+                "overlay", expectedOverlayVersion, 
core.getSolrConfig().getOverlay().getVersion())
+            | isExpectedVersionStale(
+                "params",
+                expectedParamsVersion,
+                core.getSolrConfig().getRequestParams().getZnodeVersion());
+    if (isStale && core.getResourceLoader() instanceof ZkSolrResourceLoader) {
+      final Lock reloadLock =
+          ((SolrConfigHandler) 
core.getRequestHandler("/config")).getReloadLock();
+      new Thread(
+              () -> {
+                if (!reloadLock.tryLock()) {
+                  log.info("Another reload is in progress . Not doing 
anything");
+                  return;
+                }
+                try {
+                  log.info("Trying to update my configs");
+                  SolrCore.getConfListener(core, (ZkSolrResourceLoader) 
core.getResourceLoader())
+                      .run();
+                } catch (Exception e) {
+                  log.error("Unable to refresh conf ", e);
+                } finally {
+                  reloadLock.unlock();
+                }
+              },
+              SolrConfigHandler.class.getSimpleName() + "-refreshconf")
+          .start();
+    } else {
+      if (log.isInfoEnabled()) {
+        log.info(
+            "isStale {} , resourceloader {}",
+            isStale,
+            core.getResourceLoader().getClass().getName());
+      }
+    }
+  }
+
+  private static boolean isExpectedVersionStale(String label, int expected, 
int actual) {
+    if (expected == -1) {
+      return false;
+    }
+    if (expected > actual) {
+      log.info("expecting {} version {} but my version is {}", label, 
expected, actual);
+      return true;
+    }
+    log.info("I already have the expected version {} of {}", expected, label);
+    return false;
+  }
+
   @Override
   public Name getPermissionName(AuthorizationContext ctx) {
     switch (ctx.getHttpMethod()) {
diff --git 
a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java 
b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java
index d46738ea347..80d46e7bac6 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfig.java
@@ -30,6 +30,8 @@ import java.util.Map;
 import org.apache.solr.api.JerseyResource;
 import org.apache.solr.client.api.endpoint.ConfigApi;
 import org.apache.solr.client.api.model.ConfigInfoResponse;
+import org.apache.solr.client.api.model.ConfigOverlayResponse;
+import org.apache.solr.client.api.model.ConfigZnodeVersionResponse;
 import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
@@ -37,6 +39,7 @@ import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.common.util.Utils;
 import org.apache.solr.core.PluginInfo;
 import org.apache.solr.handler.RequestHandlerBase;
+import org.apache.solr.handler.SolrConfigHandler;
 import org.apache.solr.jersey.NullKeyTolerantMap;
 import org.apache.solr.jersey.PermissionName;
 import org.apache.solr.request.SolrQueryRequest;
@@ -60,6 +63,32 @@ public class GetConfig extends JerseyResource implements 
ConfigApi.Get {
     return response;
   }
 
+  @Override
+  @PermissionName(CONFIG_READ_PERM)
+  public ConfigOverlayResponse getOverlay() {
+    final var response = 
instantiateJerseyResponse(ConfigOverlayResponse.class);
+    response.overlay =
+        Utils.convertToMap(
+            solrQueryRequest.getCore().getSolrConfig().getOverlay(), new 
LinkedHashMap<>());
+    return response;
+  }
+
+  @Override
+  @PermissionName(CONFIG_READ_PERM)
+  public ConfigZnodeVersionResponse getZnodeVersion(
+      int expectedOverlayVersion, int expectedParamsVersion) {
+    final var response = 
instantiateJerseyResponse(ConfigZnodeVersionResponse.class);
+    final var core = solrQueryRequest.getCore();
+    final var solrConfig = core.getSolrConfig();
+
+    response.znodeVersion = new ConfigZnodeVersionResponse.ZnodeVersions();
+    response.znodeVersion.overlay = solrConfig.getOverlay().getVersion();
+    response.znodeVersion.params = 
solrConfig.getRequestParams().getZnodeVersion();
+
+    SolrConfigHandler.maybeRefreshStaleConfig(core, expectedOverlayVersion, 
expectedParamsVersion);
+    return response;
+  }
+
   @SuppressWarnings({"unchecked"})
   private Map<String, Object> buildConfigMap(
       SolrQueryRequest solrQueryRequest, boolean expandParams) {
diff --git 
a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java 
b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java
index 2a2db95683e..6a0567c987c 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetConfigAPI.java
@@ -59,8 +59,6 @@ public class GetConfigAPI {
   // Delete a path from this list when that section is migrated to Jersey
   @EndPoint(
       path = {
-        "/config/overlay",
-        "/config/znodeVersion",
         "/config/luceneMatchVersion",
         "/config/query",
         "/config/requestHandler",
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java 
b/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java
index 0498b25dd5c..252946a5971 100644
--- 
a/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java
+++ 
b/solr/core/src/test/org/apache/solr/handler/admin/V2ConfigAPIMappingTest.java
@@ -49,11 +49,9 @@ public class V2ConfigAPIMappingTest extends 
V2ApiMappingTest<SolrConfigHandler>
   // the API lookup works for a handful of the valid config "components".
   @Test
   public void testGetSingleComponentConfig() {
-    assertAnnotatedApiExistsFor("GET", "/config/overlay");
     assertAnnotatedApiExistsFor("GET", "/config/query");
     assertAnnotatedApiExistsFor("GET", "/config/jmx");
     assertAnnotatedApiExistsFor("GET", "/config/requestDispatcher");
-    assertAnnotatedApiExistsFor("GET", "/config/znodeVersion");
     assertAnnotatedApiExistsFor("GET", "/config/luceneMatchVersion");
     assertAnnotatedApiExistsFor("GET", "/config/indexConfigdeletionPolicy");
     assertAnnotatedApiExistsFor("GET", "/config/updateHandlerupdateLog");
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java
 
b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java
index 297da96353d..7ce43a5ff3d 100644
--- 
a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java
+++ 
b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigSolrCloudTest.java
@@ -40,7 +40,7 @@ public class GetConfigSolrCloudTest extends SolrCloudTestCase 
{
   }
 
   @Test
-  public void testGetConfigFromCore() throws Exception {
+  public void testGetConfigFromCollection() throws Exception {
     var request = new ConfigApi.GetConfig(IndexType.COLLECTION, 
COLLECTION_NAME);
     var response = request.process(cluster.getSolrClient());
 
@@ -52,4 +52,28 @@ public class GetConfigSolrCloudTest extends 
SolrCloudTestCase {
     assertTrue(response.config.containsKey("query"));
     assertTrue(response.config.containsKey("requestHandler"));
   }
+
+  @Test
+  public void testGetOverlayFromCollection() throws Exception {
+    var request = new ConfigApi.GetOverlay(IndexType.COLLECTION, 
COLLECTION_NAME);
+    var response = request.process(cluster.getSolrClient());
+
+    assertNotNull(response);
+    assertNull(response.error);
+    assertNotNull(response.overlay);
+    assertTrue(response.overlay.containsKey("znodeVersion"));
+    assertEquals(-1, response.overlay.get("znodeVersion"));
+  }
+
+  @Test
+  public void testGetZnodeVersionFromCollection() throws Exception {
+    var request = new ConfigApi.GetZnodeVersion(IndexType.COLLECTION, 
COLLECTION_NAME);
+    var response = request.process(cluster.getSolrClient());
+
+    assertNotNull(response);
+    assertNull(response.error);
+    assertNotNull(response.znodeVersion);
+    assertTrue(response.znodeVersion.overlay >= -1);
+    assertTrue(response.znodeVersion.params >= -1);
+  }
 }
diff --git 
a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java 
b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java
index c122e8d497a..a17d9258a18 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetConfigTest.java
@@ -56,4 +56,28 @@ public class GetConfigTest extends SolrTestCase {
     assertTrue(response.config.containsKey("searchComponent"));
     assertTrue(response.config.containsKey("updateProcessor"));
   }
+
+  @Test
+  public void testGetOverlayFromCore() throws Exception {
+    var request = new ConfigApi.GetOverlay(IndexType.CORE, CORE_NAME);
+    var response = request.process(solrTestRule.getSolrClient(CORE_NAME));
+
+    assertNotNull(response);
+    assertNull(response.error);
+    assertNotNull(response.overlay);
+    assertTrue(response.overlay.containsKey("znodeVersion"));
+    assertEquals(-1, response.overlay.get("znodeVersion"));
+  }
+
+  @Test
+  public void testGetZnodeVersionFromCore() throws Exception {
+    var request = new ConfigApi.GetZnodeVersion(IndexType.CORE, CORE_NAME);
+    var response = request.process(solrTestRule.getSolrClient(CORE_NAME));
+
+    assertNotNull(response);
+    assertNull(response.error);
+    assertNotNull(response.znodeVersion);
+    assertTrue(response.znodeVersion.overlay >= -1);
+    assertTrue(response.znodeVersion.params >= -1);
+  }
 }
diff --git a/solr/solrj/src/resources/java-template/api.mustache 
b/solr/solrj/src/resources/java-template/api.mustache
index 4aae4828561..b8c0dce8168 100644
--- a/solr/solrj/src/resources/java-template/api.mustache
+++ b/solr/solrj/src/resources/java-template/api.mustache
@@ -233,14 +233,14 @@ public class {{classname}} {
 
             @Override
             public SolrParams getParams() {
-              final ModifiableSolrParams params = new ModifiableSolrParams();
+              final ModifiableSolrParams solrParams = new 
ModifiableSolrParams();
               {{#queryParams}}
               if ({{paramName}} != null) {
-                  {{#isArray}}{{paramName}}.forEach(v -> 
params.add("{{baseName}}", 
v{{^items.isString}}.toString(){{/items.isString}}));{{/isArray}}
-                  {{^isArray}}params.add("{{baseName}}", 
{{paramName}}{{^isString}}.toString(){{/isString}});{{/isArray}}
+                  {{#isArray}}{{paramName}}.forEach(v -> 
solrParams.add("{{baseName}}", 
v{{^items.isString}}.toString(){{/items.isString}}));{{/isArray}}
+                  {{^isArray}}solrParams.add("{{baseName}}", 
{{paramName}}{{^isString}}.toString(){{/isString}});{{/isArray}}
               }
               {{/queryParams}}
-              return params;
+              return solrParams;
             }
 
             @Override

Reply via email to