You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@solr.apache.org by ge...@apache.org on 2023/09/27 17:40:12 UTC

[solr] branch SOLR-16825-migrate-definitions-to-api-module-pt4 created (now 34f2d7a29d1)

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

gerlowskija pushed a change to branch SOLR-16825-migrate-definitions-to-api-module-pt4
in repository https://gitbox.apache.org/repos/asf/solr.git


      at 34f2d7a29d1 Amend post-v2-request logging to handle reflected types

This branch includes the following new commits:

     new 9a1fd0fd41f Fix test
     new 0f68b36ab5a Migrade add-replica to 'api' module
     new 0ebd7ea84e0 Migrade create-shard to 'api' module
     new bbce1a0609d Migrade install-shard-data to 'api' module
     new 1896fdde26b Migrade install-core-data to 'api' module
     new 34f2d7a29d1 Amend post-v2-request logging to handle reflected types

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.



[solr] 03/06: Migrade create-shard to 'api' module

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

gerlowskija pushed a commit to branch SOLR-16825-migrate-definitions-to-api-module-pt4
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 0ebd7ea84e0cbfda4f4a6a40d14fc3f895038295
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Wed Sep 27 09:53:01 2023 -0400

    Migrade create-shard to 'api' module
---
 .../solr/client/api/endpoint/CreateShardApi.java   |  37 +++++++
 .../client/api/model/CreateShardRequestBody.java   |  50 ++++++++++
 .../solr/handler/admin/CollectionsHandler.java     |   6 +-
 .../api/{CreateShardAPI.java => CreateShard.java}  | 110 ++++++---------------
 .../solr/handler/admin/api/CreateShardAPITest.java |  27 ++---
 5 files changed, 135 insertions(+), 95 deletions(-)

diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateShardApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateShardApi.java
new file mode 100644
index 00000000000..0bd30763811
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateShardApi.java
@@ -0,0 +1,37 @@
+/*
+ * 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 io.swagger.v3.oas.annotations.Operation;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import org.apache.solr.client.api.model.CreateShardRequestBody;
+import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;
+
+/** V2 API definition for creating a new shard in a collection. */
+@Path("/collections/{collectionName}/shards")
+public interface CreateShardApi {
+
+  @POST
+  @Operation(
+      summary = "Create a new shard in an existing collection",
+      tags = {"shards"})
+  SubResponseAccumulatingJerseyResponse createShard(
+      @PathParam("collectionName") String collectionName, CreateShardRequestBody requestBody)
+      throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CreateShardRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/CreateShardRequestBody.java
new file mode 100644
index 00000000000..ea871998cca
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/CreateShardRequestBody.java
@@ -0,0 +1,50 @@
+/*
+ * 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 io.swagger.v3.oas.annotations.media.Schema;
+import java.util.List;
+import java.util.Map;
+
+public class CreateShardRequestBody {
+  @Schema(name = "shardName")
+  @JsonProperty("name")
+  public String shardName;
+
+  @JsonProperty public Integer replicationFactor;
+
+  @JsonProperty public Integer nrtReplicas;
+
+  @JsonProperty public Integer tlogReplicas;
+
+  @JsonProperty public Integer pullReplicas;
+
+  @JsonProperty("createReplicas")
+  public Boolean createReplicas;
+
+  @JsonProperty("nodeSet")
+  public List<String> nodeSet;
+
+  @JsonProperty public Boolean waitForFinalState;
+
+  @JsonProperty public Boolean followAliases;
+
+  @JsonProperty public String async;
+
+  @JsonProperty public Map<String, String> properties;
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
index 5231393ea4e..5b0b97f7f07 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
@@ -176,7 +176,7 @@ import org.apache.solr.handler.admin.api.CreateCollectionAPI;
 import org.apache.solr.handler.admin.api.CreateCollectionBackupAPI;
 import org.apache.solr.handler.admin.api.CreateCollectionSnapshotAPI;
 import org.apache.solr.handler.admin.api.CreateReplica;
-import org.apache.solr.handler.admin.api.CreateShardAPI;
+import org.apache.solr.handler.admin.api.CreateShard;
 import org.apache.solr.handler.admin.api.DeleteAlias;
 import org.apache.solr.handler.admin.api.DeleteCollection;
 import org.apache.solr.handler.admin.api.DeleteCollectionBackup;
@@ -729,7 +729,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
     CREATESHARD_OP(
         CREATESHARD,
         (req, rsp, h) -> {
-          CreateShardAPI.invokeFromV1Params(h.coreContainer, req, rsp);
+          CreateShard.invokeFromV1Params(h.coreContainer, req, rsp);
           return null;
         }),
     DELETEREPLICA_OP(
@@ -1367,7 +1367,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
         CreateAliasAPI.class,
         CreateCollectionAPI.class,
         CreateCollectionBackupAPI.class,
-        CreateShardAPI.class,
+        CreateShard.class,
         DeleteAlias.class,
         DeleteCollectionBackup.class,
         DeleteCollection.class,
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShardAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java
similarity index 69%
rename from solr/core/src/java/org/apache/solr/handler/admin/api/CreateShardAPI.java
rename to solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java
index 41be6e672d7..ea07ce19191 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShardAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateShard.java
@@ -17,7 +17,6 @@
 
 package org.apache.solr.handler.admin.api;
 
-import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
 import static org.apache.solr.cloud.Overseer.QUEUE_OPERATION;
 import static org.apache.solr.cloud.api.collections.CollectionHandlingUtils.CREATE_NODE_SET;
 import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
@@ -37,16 +36,12 @@ import static org.apache.solr.common.params.CommonParams.NAME;
 import static org.apache.solr.handler.admin.api.CreateCollectionAPI.copyPrefixedPropertiesWithoutPrefix;
 import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import javax.inject.Inject;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import org.apache.solr.client.api.endpoint.CreateShardApi;
+import org.apache.solr.client.api.model.CreateShardRequestBody;
 import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;
 import org.apache.solr.client.solrj.util.SolrIdentifierValidator;
 import org.apache.solr.common.SolrException;
@@ -58,7 +53,6 @@ import org.apache.solr.common.params.CollectionParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.handler.api.V2ApiUtils;
-import org.apache.solr.jersey.JacksonReflectMapWriter;
 import org.apache.solr.jersey.PermissionName;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
@@ -69,23 +63,19 @@ import org.apache.solr.response.SolrQueryResponse;
  * <p>This API (POST /v2/collections/collectionName/shards {...}) is analogous to the v1
  * /admin/collections?action=CREATESHARD command.
  */
-@Path("/collections/{collectionName}/shards")
-public class CreateShardAPI extends AdminAPIBase {
+public class CreateShard extends AdminAPIBase implements CreateShardApi {
 
   @Inject
-  public CreateShardAPI(
+  public CreateShard(
       CoreContainer coreContainer,
       SolrQueryRequest solrQueryRequest,
       SolrQueryResponse solrQueryResponse) {
     super(coreContainer, solrQueryRequest, solrQueryResponse);
   }
 
-  @POST
-  @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
   @PermissionName(COLL_EDIT_PERM)
   public SubResponseAccumulatingJerseyResponse createShard(
-      @PathParam("collectionName") String collectionName, CreateShardRequestBody requestBody)
-      throws Exception {
+      String collectionName, CreateShardRequestBody requestBody) throws Exception {
     final var response = instantiateJerseyResponse(SubResponseAccumulatingJerseyResponse.class);
     if (requestBody == null) {
       throw new SolrException(
@@ -101,71 +91,34 @@ public class CreateShardAPI extends AdminAPIBase {
 
     final ZkNodeProps remoteMessage = createRemoteMessage(resolvedCollectionName, requestBody);
     submitRemoteMessageAndHandleResponse(
-        response,
-        CollectionParams.CollectionAction.CREATESHARD,
-        remoteMessage,
-        requestBody.asyncId);
+        response, CollectionParams.CollectionAction.CREATESHARD, remoteMessage, requestBody.async);
     return response;
   }
 
-  public static class CreateShardRequestBody implements JacksonReflectMapWriter {
-    @JsonProperty(NAME)
-    public String shardName;
-
-    @JsonProperty(REPLICATION_FACTOR)
-    public Integer replicationFactor;
-
-    @JsonProperty(NRT_REPLICAS)
-    public Integer nrtReplicas;
-
-    @JsonProperty(TLOG_REPLICAS)
-    public Integer tlogReplicas;
-
-    @JsonProperty(PULL_REPLICAS)
-    public Integer pullReplicas;
-
-    @JsonProperty("createReplicas")
-    public Boolean createReplicas;
-
-    @JsonProperty("nodeSet")
-    public List<String> nodeSet;
-
-    @JsonProperty(WAIT_FOR_FINAL_STATE)
-    public Boolean waitForFinalState;
-
-    @JsonProperty(FOLLOW_ALIASES)
-    public Boolean followAliases;
-
-    @JsonProperty(ASYNC)
-    public String asyncId;
-
-    @JsonProperty public Map<String, String> properties;
-
-    public static CreateShardRequestBody fromV1Params(SolrParams params) {
-      params.required().check(COLLECTION, SHARD);
-
-      final var requestBody = new CreateShardRequestBody();
-      requestBody.shardName = params.get(SHARD);
-      requestBody.replicationFactor = params.getInt(REPLICATION_FACTOR);
-      requestBody.nrtReplicas = params.getInt(NRT_REPLICAS);
-      requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS);
-      requestBody.pullReplicas = params.getInt(PULL_REPLICAS);
-      if (params.get(CREATE_NODE_SET_PARAM) != null) {
-        final String nodeSetStr = params.get(CREATE_NODE_SET_PARAM);
-        if ("EMPTY".equals(nodeSetStr)) {
-          requestBody.createReplicas = false;
-        } else {
-          requestBody.nodeSet = Arrays.asList(nodeSetStr.split(","));
-        }
+  public static CreateShardRequestBody createRequestBodyFromV1Params(SolrParams params) {
+    params.required().check(COLLECTION, SHARD);
+
+    final var requestBody = new CreateShardRequestBody();
+    requestBody.shardName = params.get(SHARD);
+    requestBody.replicationFactor = params.getInt(REPLICATION_FACTOR);
+    requestBody.nrtReplicas = params.getInt(NRT_REPLICAS);
+    requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS);
+    requestBody.pullReplicas = params.getInt(PULL_REPLICAS);
+    if (params.get(CREATE_NODE_SET_PARAM) != null) {
+      final String nodeSetStr = params.get(CREATE_NODE_SET_PARAM);
+      if ("EMPTY".equals(nodeSetStr)) {
+        requestBody.createReplicas = false;
+      } else {
+        requestBody.nodeSet = Arrays.asList(nodeSetStr.split(","));
       }
-      requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE);
-      requestBody.followAliases = params.getBool(FOLLOW_ALIASES);
-      requestBody.asyncId = params.get(ASYNC);
-      requestBody.properties =
-          copyPrefixedPropertiesWithoutPrefix(params, new HashMap<>(), PROPERTY_PREFIX);
-
-      return requestBody;
     }
+    requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE);
+    requestBody.followAliases = params.getBool(FOLLOW_ALIASES);
+    requestBody.async = params.get(ASYNC);
+    requestBody.properties =
+        copyPrefixedPropertiesWithoutPrefix(params, new HashMap<>(), PROPERTY_PREFIX);
+
+    return requestBody;
   }
 
   public static void invokeFromV1Params(
@@ -173,9 +126,8 @@ public class CreateShardAPI extends AdminAPIBase {
       SolrQueryRequest solrQueryRequest,
       SolrQueryResponse solrQueryResponse)
       throws Exception {
-    final var requestBody = CreateShardRequestBody.fromV1Params(solrQueryRequest.getParams());
-    final var createShardApi =
-        new CreateShardAPI(coreContainer, solrQueryRequest, solrQueryResponse);
+    final var requestBody = CreateShard.createRequestBodyFromV1Params(solrQueryRequest.getParams());
+    final var createShardApi = new CreateShard(coreContainer, solrQueryRequest, solrQueryResponse);
     final var response =
         createShardApi.createShard(solrQueryRequest.getParams().get(COLLECTION), requestBody);
     V2ApiUtils.squashIntoSolrResponseWithoutHeader(solrQueryResponse, response);
@@ -201,7 +153,7 @@ public class CreateShardAPI extends AdminAPIBase {
     insertIfNotNull(remoteMessage, PULL_REPLICAS, requestBody.pullReplicas);
     insertIfNotNull(remoteMessage, WAIT_FOR_FINAL_STATE, requestBody.waitForFinalState);
     insertIfNotNull(remoteMessage, FOLLOW_ALIASES, requestBody.followAliases);
-    insertIfNotNull(remoteMessage, ASYNC, requestBody.asyncId);
+    insertIfNotNull(remoteMessage, ASYNC, requestBody.async);
 
     if (requestBody.properties != null) {
       requestBody
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java
index 07b71d8a805..bb89fd326b5 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateShardAPITest.java
@@ -33,12 +33,13 @@ import static org.hamcrest.Matchers.containsString;
 import java.util.List;
 import java.util.Map;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.api.model.CreateShardRequestBody;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.hamcrest.MatcherAssert;
 import org.junit.Test;
 
-/** Unit tests for {@link CreateShardAPI} */
+/** Unit tests for {@link CreateShard} */
 public class CreateShardAPITest extends SolrTestCaseJ4 {
 
   @Test
@@ -47,7 +48,7 @@ public class CreateShardAPITest extends SolrTestCaseJ4 {
         expectThrows(
             SolrException.class,
             () -> {
-              final var api = new CreateShardAPI(null, null, null);
+              final var api = new CreateShard(null, null, null);
               api.createShard("someCollName", null);
             });
 
@@ -57,13 +58,13 @@ public class CreateShardAPITest extends SolrTestCaseJ4 {
 
   @Test
   public void testReportsErrorIfCollectionNameMissing() {
-    final var requestBody = new CreateShardAPI.CreateShardRequestBody();
+    final var requestBody = new CreateShardRequestBody();
     requestBody.shardName = "someShardName";
     final SolrException thrown =
         expectThrows(
             SolrException.class,
             () -> {
-              final var api = new CreateShardAPI(null, null, null);
+              final var api = new CreateShard(null, null, null);
               api.createShard(null, requestBody);
             });
 
@@ -73,13 +74,13 @@ public class CreateShardAPITest extends SolrTestCaseJ4 {
 
   @Test
   public void testReportsErrorIfShardNameMissing() {
-    final var requestBody = new CreateShardAPI.CreateShardRequestBody();
+    final var requestBody = new CreateShardRequestBody();
     requestBody.shardName = null;
     final SolrException thrown =
         expectThrows(
             SolrException.class,
             () -> {
-              final var api = new CreateShardAPI(null, null, null);
+              final var api = new CreateShard(null, null, null);
               api.createShard("someCollectionName", requestBody);
             });
 
@@ -89,13 +90,13 @@ public class CreateShardAPITest extends SolrTestCaseJ4 {
 
   @Test
   public void testReportsErrorIfShardNameIsInvalid() {
-    final var requestBody = new CreateShardAPI.CreateShardRequestBody();
+    final var requestBody = new CreateShardRequestBody();
     requestBody.shardName = "invalid$shard@name";
     final SolrException thrown =
         expectThrows(
             SolrException.class,
             () -> {
-              final var api = new CreateShardAPI(null, null, null);
+              final var api = new CreateShard(null, null, null);
               api.createShard("someCollectionName", requestBody);
             });
 
@@ -106,7 +107,7 @@ public class CreateShardAPITest extends SolrTestCaseJ4 {
 
   @Test
   public void testCreateRemoteMessageAllProperties() {
-    final var requestBody = new CreateShardAPI.CreateShardRequestBody();
+    final var requestBody = new CreateShardRequestBody();
     requestBody.shardName = "someShardName";
     requestBody.replicationFactor = 123;
     requestBody.nrtReplicas = 123;
@@ -116,11 +117,11 @@ public class CreateShardAPITest extends SolrTestCaseJ4 {
     requestBody.nodeSet = List.of("node1", "node2");
     requestBody.waitForFinalState = true;
     requestBody.followAliases = true;
-    requestBody.asyncId = "someAsyncId";
+    requestBody.async = "someAsyncId";
     requestBody.properties = Map.of("propName1", "propVal1", "propName2", "propVal2");
 
     final var remoteMessage =
-        CreateShardAPI.createRemoteMessage("someCollectionName", requestBody).getProperties();
+        CreateShard.createRemoteMessage("someCollectionName", requestBody).getProperties();
 
     assertEquals(13, remoteMessage.size());
     assertEquals("createshard", remoteMessage.get(QUEUE_OPERATION));
@@ -154,7 +155,7 @@ public class CreateShardAPITest extends SolrTestCaseJ4 {
     v1Params.add("property.propName1", "propVal1");
     v1Params.add("property.propName2", "propVal2");
 
-    final var requestBody = CreateShardAPI.CreateShardRequestBody.fromV1Params(v1Params);
+    final var requestBody = CreateShard.createRequestBodyFromV1Params(v1Params);
 
     assertEquals("someShardName", requestBody.shardName);
     assertEquals(Integer.valueOf(123), requestBody.replicationFactor);
@@ -165,7 +166,7 @@ public class CreateShardAPITest extends SolrTestCaseJ4 {
     assertEquals(List.of("node1", "node2"), requestBody.nodeSet);
     assertEquals(Boolean.TRUE, requestBody.waitForFinalState);
     assertEquals(Boolean.TRUE, requestBody.followAliases);
-    assertEquals("someAsyncId", requestBody.asyncId);
+    assertEquals("someAsyncId", requestBody.async);
     assertEquals("propVal1", requestBody.properties.get("propName1"));
     assertEquals("propVal2", requestBody.properties.get("propName2"));
   }


[solr] 06/06: Amend post-v2-request logging to handle reflected types

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

gerlowskija pushed a commit to branch SOLR-16825-migrate-definitions-to-api-module-pt4
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 34f2d7a29d1f1dad1aa2d1df2e0b8737b205033c
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Wed Sep 27 11:51:00 2023 -0400

    Amend post-v2-request logging to handle reflected types
---
 .../solr/jersey/PostRequestLoggingFilter.java      | 27 +++++++++++++---------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/jersey/PostRequestLoggingFilter.java b/solr/core/src/java/org/apache/solr/jersey/PostRequestLoggingFilter.java
index 3925b297d6a..a7a6632fa65 100644
--- a/solr/core/src/java/org/apache/solr/jersey/PostRequestLoggingFilter.java
+++ b/solr/core/src/java/org/apache/solr/jersey/PostRequestLoggingFilter.java
@@ -41,6 +41,7 @@ import javax.ws.rs.core.MultivaluedMap;
 import org.apache.solr.client.api.model.SolrJerseyResponse;
 import org.apache.solr.common.util.CollectionUtil;
 import org.apache.solr.common.util.StrUtils;
+import org.apache.solr.common.util.Utils;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.servlet.HttpSolrCall;
@@ -141,19 +142,23 @@ public class PostRequestLoggingFilter implements ContainerResponseFilter {
       return "{}";
     }
 
-    if (!(requestContext.getProperty(DESERIALIZED_REQUEST_BODY_KEY)
-        instanceof JacksonReflectMapWriter)) {
-      log.warn(
-          "Encountered unexpected request-body type {} for request {}; only {} expected.",
-          requestContext.getProperty(DESERIALIZED_REQUEST_BODY_KEY).getClass().getName(),
-          requestContext.getUriInfo().getPath(),
-          JacksonReflectMapWriter.class.getName());
-      return "{}";
+    final Object deserializedBody = requestContext.getProperty(DESERIALIZED_REQUEST_BODY_KEY);
+    if (deserializedBody instanceof JacksonReflectMapWriter) {
+      return ((JacksonReflectMapWriter) requestContext.getProperty(DESERIALIZED_REQUEST_BODY_KEY))
+          .jsonStr()
+          .replace("\n", "");
+    }
+
+    final Object reflectWritable = Utils.getReflectWriter(deserializedBody);
+    if (reflectWritable instanceof Utils.DelegateReflectWriter) {
+      return Utils.toJSONString(reflectWritable).replaceAll("\n", "");
     }
 
-    return ((JacksonReflectMapWriter) requestContext.getProperty(DESERIALIZED_REQUEST_BODY_KEY))
-        .jsonStr()
-        .replace("\n", "");
+    log.warn(
+        "No reflection data found for request-body type {} for request {}; omitting request-body details from logging",
+        deserializedBody.getClass().getName(),
+        requestContext.getUriInfo().getPath());
+    return "{}";
   }
 
   public static String filterAndStringifyQueryParameters(


[solr] 01/06: Fix test

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

gerlowskija pushed a commit to branch SOLR-16825-migrate-definitions-to-api-module-pt4
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 9a1fd0fd41f4fd3646e1c0f84d717731d4061ef6
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Tue Sep 26 15:38:59 2023 -0400

    Fix test
---
 .../org/apache/solr/handler/admin/api/CreateCollectionAPI.java | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateCollectionAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateCollectionAPI.java
index 38fb03b2020..23bd93803a2 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateCollectionAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateCollectionAPI.java
@@ -367,9 +367,13 @@ public class CreateCollectionAPI extends AdminAPIBase implements CreateCollectio
           flattenMapWithPrefix(propertiesMap, v2MapVals, CollectionAdminParams.PROPERTY_PREFIX);
           break;
         case ROUTER_KEY:
-          final Map<String, Object> routerProperties =
-              (Map<String, Object>) v2MapVals.remove(V2ApiConstants.ROUTER_KEY);
-          flattenMapWithPrefix(routerProperties, v2MapVals, CollectionAdminParams.ROUTER_PREFIX);
+          final var routerProperties =
+              (CreateCollectionRouterProperties) v2MapVals.remove(ROUTER_KEY);
+          final Map<String, Object> routerPropertiesAsMap =
+              ((Utils.DelegateReflectWriter) Utils.getReflectWriter(routerProperties))
+                  .toMap(new HashMap<>());
+          flattenMapWithPrefix(
+              routerPropertiesAsMap, v2MapVals, CollectionAdminParams.ROUTER_PREFIX);
           break;
         case V2ApiConstants.CONFIG:
           v2MapVals.put(CollectionAdminParams.COLL_CONF, v2MapVals.remove(V2ApiConstants.CONFIG));


[solr] 02/06: Migrade add-replica to 'api' module

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

gerlowskija pushed a commit to branch SOLR-16825-migrate-definitions-to-api-module-pt4
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 0f68b36ab5a4181932db2f942387bf0c871bac60
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Tue Sep 26 16:30:15 2023 -0400

    Migrade add-replica to 'api' module
---
 .../solr/client/api/endpoint/CreateReplicaApi.java |  44 +++++++++
 .../client/api/model/CreateReplicaRequestBody.java |  48 ++++++++++
 .../solr/handler/admin/CollectionsHandler.java     |   9 +-
 .../{CreateReplicaAPI.java => CreateReplica.java}  | 105 +++++++--------------
 .../handler/admin/api/CreateReplicaAPITest.java    |  23 ++---
 .../solr/jersey/PostRequestLoggingFilterTest.java  |   6 +-
 6 files changed, 144 insertions(+), 91 deletions(-)

diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateReplicaApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateReplicaApi.java
new file mode 100644
index 00000000000..21c26ea8f49
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/CreateReplicaApi.java
@@ -0,0 +1,44 @@
+/*
+ * 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 io.swagger.v3.oas.annotations.Operation;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import org.apache.solr.client.api.model.CreateReplicaRequestBody;
+import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;
+
+/**
+ * V2 API definition for adding a new replica to an existing shard.
+ *
+ * <p>This API (POST /v2/collections/cName/shards/sName/replicas {...}) is analogous to the v1
+ * /admin/collections?action=ADDREPLICA command.
+ */
+@Path("/collections/{collectionName}/shards/{shardName}/replicas")
+public interface CreateReplicaApi {
+
+  @POST
+  @Operation(
+      summary = "Creates a new replica of an existing shard.",
+      tags = {"replicas"})
+  SubResponseAccumulatingJerseyResponse createReplica(
+      @PathParam("collectionName") String collectionName,
+      @PathParam("shardName") String shardName,
+      CreateReplicaRequestBody requestBody)
+      throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/CreateReplicaRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/CreateReplicaRequestBody.java
new file mode 100644
index 00000000000..a669cdaf414
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/CreateReplicaRequestBody.java
@@ -0,0 +1,48 @@
+/*
+ * 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;
+import java.util.Map;
+
+public class CreateReplicaRequestBody {
+  @JsonProperty public String name;
+  @JsonProperty public String type; // TODO Make this an enum - see SOLR-15796
+  @JsonProperty public String instanceDir;
+  @JsonProperty public String dataDir;
+  @JsonProperty public String ulogDir;
+  @JsonProperty public String route;
+  @JsonProperty public Integer nrtReplicas;
+  @JsonProperty public Integer tlogReplicas;
+  @JsonProperty public Integer pullReplicas;
+  @JsonProperty public Boolean waitForFinalState;
+  @JsonProperty public Boolean followAliases;
+
+  @JsonProperty public String async;
+
+  // TODO This cluster of properties could probably be simplified down to just "nodeSet".  See
+  // SOLR-15542
+  @JsonProperty public String node;
+
+  @JsonProperty("nodeSet")
+  public List<String> nodeSet;
+
+  @JsonProperty public Boolean skipNodeAssignment;
+
+  @JsonProperty public Map<String, String> properties;
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
index a3ebbf4ae95..5231393ea4e 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
@@ -175,7 +175,7 @@ import org.apache.solr.handler.admin.api.CreateAliasAPI;
 import org.apache.solr.handler.admin.api.CreateCollectionAPI;
 import org.apache.solr.handler.admin.api.CreateCollectionBackupAPI;
 import org.apache.solr.handler.admin.api.CreateCollectionSnapshotAPI;
-import org.apache.solr.handler.admin.api.CreateReplicaAPI;
+import org.apache.solr.handler.admin.api.CreateReplica;
 import org.apache.solr.handler.admin.api.CreateShardAPI;
 import org.apache.solr.handler.admin.api.DeleteAlias;
 import org.apache.solr.handler.admin.api.DeleteCollection;
@@ -942,9 +942,8 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
           final var params = req.getParams();
           params.required().check(COLLECTION_PROP, SHARD_ID_PROP);
 
-          final var api = new CreateReplicaAPI(h.coreContainer, req, rsp);
-          final var requestBody =
-              CreateReplicaAPI.AddReplicaRequestBody.fromV1Params(req.getParams());
+          final var api = new CreateReplica(h.coreContainer, req, rsp);
+          final var requestBody = CreateReplica.createRequestBodyFromV1Params(req.getParams());
           final var response =
               api.createReplica(
                   params.get(COLLECTION_PROP), params.get(SHARD_ID_PROP), requestBody);
@@ -1362,7 +1361,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
   @Override
   public Collection<Class<? extends JerseyResource>> getJerseyResources() {
     return List.of(
-        CreateReplicaAPI.class,
+        CreateReplica.class,
         AddReplicaProperty.class,
         BalanceShardUniqueAPI.class,
         CreateAliasAPI.class,
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplicaAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java
similarity index 66%
rename from solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplicaAPI.java
rename to solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java
index c119f27db60..2f34556dbda 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplicaAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/CreateReplica.java
@@ -17,7 +17,6 @@
 
 package org.apache.solr.handler.admin.api;
 
-import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
 import static org.apache.solr.cloud.Overseer.QUEUE_OPERATION;
 import static org.apache.solr.cloud.api.collections.CollectionHandlingUtils.CREATE_NODE_SET;
 import static org.apache.solr.common.cloud.ZkStateReader.COLLECTION_PROP;
@@ -41,16 +40,12 @@ import static org.apache.solr.common.params.ShardParams._ROUTE_;
 import static org.apache.solr.handler.admin.api.CreateCollectionAPI.copyPrefixedPropertiesWithoutPrefix;
 import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
 import java.util.Arrays;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 import javax.inject.Inject;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import org.apache.solr.client.api.endpoint.CreateReplicaApi;
+import org.apache.solr.client.api.model.CreateReplicaRequestBody;
 import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.cloud.ZkNodeProps;
@@ -59,35 +54,29 @@ import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.CollectionUtil;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.jersey.JacksonReflectMapWriter;
 import org.apache.solr.jersey.PermissionName;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
 
 /**
- * V2 API for adding a new replica to an existing shard.
+ * V2 API implementation for adding a new replica to an existing shard.
  *
  * <p>This API (POST /v2/collections/cName/shards/sName/replicas {...}) is analogous to the v1
  * /admin/collections?action=ADDREPLICA command.
  */
-@Path("/collections/{collectionName}/shards/{shardName}/replicas")
-public class CreateReplicaAPI extends AdminAPIBase {
+public class CreateReplica extends AdminAPIBase implements CreateReplicaApi {
 
   @Inject
-  public CreateReplicaAPI(
+  public CreateReplica(
       CoreContainer coreContainer,
       SolrQueryRequest solrQueryRequest,
       SolrQueryResponse solrQueryResponse) {
     super(coreContainer, solrQueryRequest, solrQueryResponse);
   }
 
-  @POST
-  @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
   @PermissionName(COLL_EDIT_PERM)
   public SubResponseAccumulatingJerseyResponse createReplica(
-      @PathParam("collectionName") String collectionName,
-      @PathParam("shardName") String shardName,
-      AddReplicaRequestBody requestBody)
+      String collectionName, String shardName, CreateReplicaRequestBody requestBody)
       throws Exception {
     final var response = instantiateJerseyResponse(SubResponseAccumulatingJerseyResponse.class);
     if (requestBody == null) {
@@ -103,12 +92,12 @@ public class CreateReplicaAPI extends AdminAPIBase {
     final ZkNodeProps remoteMessage =
         createRemoteMessage(resolvedCollectionName, shardName, requestBody);
     submitRemoteMessageAndHandleResponse(
-        response, CollectionParams.CollectionAction.ADDREPLICA, remoteMessage, requestBody.asyncId);
+        response, CollectionParams.CollectionAction.ADDREPLICA, remoteMessage, requestBody.async);
     return response;
   }
 
   public static ZkNodeProps createRemoteMessage(
-      String collectionName, String shardName, AddReplicaRequestBody requestBody) {
+      String collectionName, String shardName, CreateReplicaRequestBody requestBody) {
     final Map<String, Object> remoteMessage = new HashMap<>();
     remoteMessage.put(QUEUE_OPERATION, CollectionParams.CollectionAction.ADDREPLICA.toLower());
     remoteMessage.put(COLLECTION_PROP, collectionName);
@@ -129,7 +118,7 @@ public class CreateReplicaAPI extends AdminAPIBase {
     insertIfNotNull(remoteMessage, TLOG_REPLICAS, requestBody.tlogReplicas);
     insertIfNotNull(remoteMessage, PULL_REPLICAS, requestBody.pullReplicas);
     insertIfNotNull(remoteMessage, FOLLOW_ALIASES, requestBody.followAliases);
-    insertIfNotNull(remoteMessage, ASYNC, requestBody.asyncId);
+    insertIfNotNull(remoteMessage, ASYNC, requestBody.async);
 
     if (requestBody.properties != null) {
       requestBody
@@ -144,59 +133,31 @@ public class CreateReplicaAPI extends AdminAPIBase {
     return new ZkNodeProps(remoteMessage);
   }
 
-  public static class AddReplicaRequestBody implements JacksonReflectMapWriter {
-    @JsonProperty public String name;
-    @JsonProperty public String type; // TODO Make this an enum - see SOLR-15796
-    @JsonProperty public String instanceDir;
-    @JsonProperty public String dataDir;
-    @JsonProperty public String ulogDir;
-    @JsonProperty public String route;
-    @JsonProperty public Integer nrtReplicas;
-    @JsonProperty public Integer tlogReplicas;
-    @JsonProperty public Integer pullReplicas;
-    @JsonProperty public Boolean waitForFinalState;
-    @JsonProperty public Boolean followAliases;
-
-    @JsonProperty(ASYNC)
-    public String asyncId;
-
-    // TODO This cluster of properties could probably be simplified down to just "nodeSet".  See
-    // SOLR-15542
-    @JsonProperty public String node;
-
-    @JsonProperty("nodeSet")
-    public List<String> nodeSet;
-
-    @JsonProperty public Boolean skipNodeAssignment;
-
-    @JsonProperty public Map<String, String> properties;
-
-    public static AddReplicaRequestBody fromV1Params(SolrParams params) {
-      final var requestBody = new AddReplicaRequestBody();
-
-      requestBody.name = params.get(NAME);
-      requestBody.type = params.get(REPLICA_TYPE);
-      requestBody.instanceDir = params.get(INSTANCE_DIR);
-      requestBody.dataDir = params.get(DATA_DIR);
-      requestBody.ulogDir = params.get(ULOG_DIR);
-      requestBody.route = params.get(_ROUTE_);
-      requestBody.nrtReplicas = params.getInt(NRT_REPLICAS);
-      requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS);
-      requestBody.pullReplicas = params.getInt(PULL_REPLICAS);
-      requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE);
-      requestBody.followAliases = params.getBool(FOLLOW_ALIASES);
-      requestBody.asyncId = params.get(ASYNC);
-
-      requestBody.node = params.get(NODE);
-      if (params.get(CREATE_NODE_SET_PARAM) != null) {
-        requestBody.nodeSet = Arrays.asList(params.get(CREATE_NODE_SET).split(","));
-      }
-      requestBody.skipNodeAssignment = params.getBool(SKIP_NODE_ASSIGNMENT);
+  public static CreateReplicaRequestBody createRequestBodyFromV1Params(SolrParams params) {
+    final var requestBody = new CreateReplicaRequestBody();
+
+    requestBody.name = params.get(NAME);
+    requestBody.type = params.get(REPLICA_TYPE);
+    requestBody.instanceDir = params.get(INSTANCE_DIR);
+    requestBody.dataDir = params.get(DATA_DIR);
+    requestBody.ulogDir = params.get(ULOG_DIR);
+    requestBody.route = params.get(_ROUTE_);
+    requestBody.nrtReplicas = params.getInt(NRT_REPLICAS);
+    requestBody.tlogReplicas = params.getInt(TLOG_REPLICAS);
+    requestBody.pullReplicas = params.getInt(PULL_REPLICAS);
+    requestBody.waitForFinalState = params.getBool(WAIT_FOR_FINAL_STATE);
+    requestBody.followAliases = params.getBool(FOLLOW_ALIASES);
+    requestBody.async = params.get(ASYNC);
+
+    requestBody.node = params.get(NODE);
+    if (params.get(CREATE_NODE_SET_PARAM) != null) {
+      requestBody.nodeSet = Arrays.asList(params.get(CREATE_NODE_SET).split(","));
+    }
+    requestBody.skipNodeAssignment = params.getBool(SKIP_NODE_ASSIGNMENT);
 
-      requestBody.properties =
-          copyPrefixedPropertiesWithoutPrefix(params, new HashMap<>(), PROPERTY_PREFIX);
+    requestBody.properties =
+        copyPrefixedPropertiesWithoutPrefix(params, new HashMap<>(), PROPERTY_PREFIX);
 
-      return requestBody;
-    }
+    return requestBody;
   }
 }
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java
index d4e9772e866..2abe5d13397 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/CreateReplicaAPITest.java
@@ -39,11 +39,12 @@ import static org.apache.solr.common.params.ShardParams._ROUTE_;
 import java.util.List;
 import java.util.Map;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.api.model.CreateReplicaRequestBody;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.junit.Test;
 
-/** Unit tests for {@link CreateReplicaAPI} */
+/** Unit tests for {@link CreateReplica} */
 public class CreateReplicaAPITest extends SolrTestCaseJ4 {
   @Test
   public void testReportsErrorIfRequestBodyMissing() {
@@ -51,7 +52,7 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
         expectThrows(
             SolrException.class,
             () -> {
-              final var api = new CreateReplicaAPI(null, null, null);
+              final var api = new CreateReplica(null, null, null);
               api.createReplica("someCollName", "someShardName", null);
             });
 
@@ -61,12 +62,12 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
 
   @Test
   public void testReportsErrorIfCollectionNameMissing() {
-    final var requestBody = new CreateReplicaAPI.AddReplicaRequestBody();
+    final var requestBody = new CreateReplicaRequestBody();
     final SolrException thrown =
         expectThrows(
             SolrException.class,
             () -> {
-              final var api = new CreateReplicaAPI(null, null, null);
+              final var api = new CreateReplica(null, null, null);
               api.createReplica(null, "shardName", requestBody);
             });
 
@@ -76,12 +77,12 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
 
   @Test
   public void testReportsErrorIfShardNameMissing() {
-    final var requestBody = new CreateReplicaAPI.AddReplicaRequestBody();
+    final var requestBody = new CreateReplicaRequestBody();
     final SolrException thrown =
         expectThrows(
             SolrException.class,
             () -> {
-              final var api = new CreateReplicaAPI(null, null, null);
+              final var api = new CreateReplica(null, null, null);
               api.createReplica("someCollectionName", null, requestBody);
             });
 
@@ -91,7 +92,7 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
 
   @Test
   public void testCreateRemoteMessageAllProperties() {
-    final var requestBody = new CreateReplicaAPI.AddReplicaRequestBody();
+    final var requestBody = new CreateReplicaRequestBody();
     requestBody.name = "someName";
     requestBody.type = "NRT";
     requestBody.instanceDir = "/some/dir1";
@@ -106,11 +107,11 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
     requestBody.skipNodeAssignment = Boolean.TRUE;
     requestBody.waitForFinalState = true;
     requestBody.followAliases = true;
-    requestBody.asyncId = "someAsyncId";
+    requestBody.async = "someAsyncId";
     requestBody.properties = Map.of("propName1", "propVal1", "propName2", "propVal2");
 
     final var remoteMessage =
-        CreateReplicaAPI.createRemoteMessage("someCollectionName", "someShardName", requestBody)
+        CreateReplica.createRemoteMessage("someCollectionName", "someShardName", requestBody)
             .getProperties();
 
     assertEquals(20, remoteMessage.size());
@@ -159,7 +160,7 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
     v1Params.add("property.propName1", "propVal1");
     v1Params.add("property.propName2", "propVal2");
 
-    final var requestBody = CreateReplicaAPI.AddReplicaRequestBody.fromV1Params(v1Params);
+    final var requestBody = CreateReplica.createRequestBodyFromV1Params(v1Params);
 
     assertEquals("someName", requestBody.name);
     assertEquals("NRT", requestBody.type);
@@ -175,7 +176,7 @@ public class CreateReplicaAPITest extends SolrTestCaseJ4 {
     assertEquals(Boolean.TRUE, requestBody.skipNodeAssignment);
     assertEquals(Boolean.TRUE, requestBody.waitForFinalState);
     assertEquals(Boolean.TRUE, requestBody.followAliases);
-    assertEquals("someAsyncId", requestBody.asyncId);
+    assertEquals("someAsyncId", requestBody.async);
     assertEquals("propVal1", requestBody.properties.get("propName1"));
     assertEquals("propVal2", requestBody.properties.get("propName2"));
   }
diff --git a/solr/core/src/test/org/apache/solr/jersey/PostRequestLoggingFilterTest.java b/solr/core/src/test/org/apache/solr/jersey/PostRequestLoggingFilterTest.java
index c0770c4912e..985085b7829 100644
--- a/solr/core/src/test/org/apache/solr/jersey/PostRequestLoggingFilterTest.java
+++ b/solr/core/src/test/org/apache/solr/jersey/PostRequestLoggingFilterTest.java
@@ -26,7 +26,7 @@ import javax.ws.rs.container.ContainerRequestContext;
 import javax.ws.rs.core.MultivaluedHashMap;
 import javax.ws.rs.core.UriInfo;
 import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.handler.admin.api.CreateReplicaAPI;
+import org.apache.solr.client.api.model.CreateReplicaRequestBody;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
@@ -122,10 +122,10 @@ public class PostRequestLoggingFilterTest extends SolrTestCaseJ4 {
 
   @Test
   public void testRequestBodyRepresentedAsJsonWhenFound() {
-    final var requestBody = new CreateReplicaAPI.AddReplicaRequestBody();
+    final var requestBody = new CreateReplicaRequestBody();
     requestBody.name = "someReplicaName";
     requestBody.type = "NRT";
-    requestBody.asyncId = "someAsyncId";
+    requestBody.async = "someAsyncId";
     final var mockContext = mock(ContainerRequestContext.class);
     when(mockContext.getProperty(DESERIALIZED_REQUEST_BODY_KEY)).thenReturn(requestBody);
 


[solr] 04/06: Migrade install-shard-data to 'api' module

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

gerlowskija pushed a commit to branch SOLR-16825-migrate-definitions-to-api-module-pt4
in repository https://gitbox.apache.org/repos/asf/solr.git

commit bbce1a0609d729863b39a1fe7e18d7585738cda8
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Wed Sep 27 10:08:09 2023 -0400

    Migrade install-shard-data to 'api' module
---
 .../client/api/endpoint/InstallShardDataApi.java   | 38 +++++++++++++++++++
 .../api/model/InstallShardDataRequestBody.java     | 28 ++++++++++++++
 .../solr/handler/admin/CollectionsHandler.java     | 12 +++---
 ...tallShardDataAPI.java => InstallShardData.java} | 44 ++++------------------
 .../org/apache/solr/gcs/GCSInstallShardTest.java   |  3 +-
 .../org/apache/solr/s3/S3InstallShardTest.java     |  3 +-
 .../api/collections/AbstractInstallShardTest.java  |  3 +-
 7 files changed, 86 insertions(+), 45 deletions(-)

diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/InstallShardDataApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/InstallShardDataApi.java
new file mode 100644
index 00000000000..65648ad9117
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/InstallShardDataApi.java
@@ -0,0 +1,38 @@
+/*
+ * 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 io.swagger.v3.oas.annotations.Operation;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import org.apache.solr.client.api.model.InstallShardDataRequestBody;
+import org.apache.solr.client.api.model.SolrJerseyResponse;
+
+/** V2 API definition allowing users to import offline-constructed index into a shard. */
+@Path("/collections/{collName}/shards/{shardName}/install")
+public interface InstallShardDataApi {
+  @POST
+  @Operation(
+      summary = "Install offline index into an existing shard",
+      tags = {"shards"})
+  SolrJerseyResponse installShardData(
+      @PathParam("collName") String collName,
+      @PathParam("shardName") String shardName,
+      InstallShardDataRequestBody requestBody)
+      throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/InstallShardDataRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/InstallShardDataRequestBody.java
new file mode 100644
index 00000000000..31bec8eb434
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/InstallShardDataRequestBody.java
@@ -0,0 +1,28 @@
+/*
+ * 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 InstallShardDataRequestBody {
+  @JsonProperty(value = "location", required = true)
+  public String location;
+
+  @JsonProperty public String repository;
+
+  @JsonProperty public String async;
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
index 5b0b97f7f07..808fb8491e7 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
@@ -123,6 +123,7 @@ import org.apache.solr.api.AnnotatedApi;
 import org.apache.solr.api.Api;
 import org.apache.solr.api.JerseyResource;
 import org.apache.solr.client.api.model.AddReplicaPropertyRequestBody;
+import org.apache.solr.client.api.model.InstallShardDataRequestBody;
 import org.apache.solr.client.api.model.ReplaceNodeRequestBody;
 import org.apache.solr.client.api.model.SolrJerseyResponse;
 import org.apache.solr.client.api.model.UpdateAliasPropertiesRequestBody;
@@ -186,7 +187,7 @@ import org.apache.solr.handler.admin.api.DeleteReplica;
 import org.apache.solr.handler.admin.api.DeleteReplicaProperty;
 import org.apache.solr.handler.admin.api.DeleteShardAPI;
 import org.apache.solr.handler.admin.api.ForceLeader;
-import org.apache.solr.handler.admin.api.InstallShardDataAPI;
+import org.apache.solr.handler.admin.api.InstallShardData;
 import org.apache.solr.handler.admin.api.ListAliases;
 import org.apache.solr.handler.admin.api.ListCollectionBackups;
 import org.apache.solr.handler.admin.api.ListCollectionSnapshotsAPI;
@@ -1080,13 +1081,12 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
           req.getParams().required().check(COLLECTION, SHARD);
           final String collectionName = req.getParams().get(COLLECTION);
           final String shardName = req.getParams().get(SHARD);
-          final InstallShardDataAPI.InstallShardRequestBody reqBody =
-              new InstallShardDataAPI.InstallShardRequestBody();
-          reqBody.asyncId = req.getParams().get(ASYNC);
+          final InstallShardDataRequestBody reqBody = new InstallShardDataRequestBody();
+          reqBody.async = req.getParams().get(ASYNC);
           reqBody.repository = req.getParams().get(BACKUP_REPOSITORY);
           reqBody.location = req.getParams().get(BACKUP_LOCATION);
 
-          final InstallShardDataAPI installApi = new InstallShardDataAPI(h.coreContainer, req, rsp);
+          final InstallShardData installApi = new InstallShardData(h.coreContainer, req, rsp);
           final SolrJerseyResponse installResponse =
               installApi.installShardData(collectionName, shardName, reqBody);
           V2ApiUtils.squashIntoSolrResponseWithoutHeader(rsp, installResponse);
@@ -1375,7 +1375,7 @@ public class CollectionsHandler extends RequestHandlerBase implements Permission
         DeleteReplicaProperty.class,
         DeleteShardAPI.class,
         ForceLeader.class,
-        InstallShardDataAPI.class,
+        InstallShardData.class,
         ListCollections.class,
         ListCollectionBackups.class,
         ReloadCollectionAPI.class,
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/InstallShardDataAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/InstallShardData.java
similarity index 78%
rename from solr/core/src/java/org/apache/solr/handler/admin/api/InstallShardDataAPI.java
rename to solr/core/src/java/org/apache/solr/handler/admin/api/InstallShardData.java
index fa400835a4f..cd72071fc05 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/InstallShardDataAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/InstallShardData.java
@@ -17,18 +17,13 @@
 
 package org.apache.solr.handler.admin.api;
 
-import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
 import static org.apache.solr.handler.admin.CollectionsHandler.DEFAULT_COLLECTION_OP_TIMEOUT;
 import static org.apache.solr.security.PermissionNameProvider.Name.COLL_EDIT_PERM;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.lang.invoke.MethodHandles;
 import java.util.HashMap;
 import javax.inject.Inject;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import org.apache.solr.client.api.endpoint.InstallShardDataApi;
+import org.apache.solr.client.api.model.InstallShardDataRequestBody;
 import org.apache.solr.client.api.model.SolrJerseyResponse;
 import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.cloud.api.collections.InstallShardDataCmd;
@@ -41,42 +36,30 @@ import org.apache.solr.common.params.CollectionParams;
 import org.apache.solr.common.util.StrUtils;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.handler.admin.CollectionsHandler;
-import org.apache.solr.jersey.JacksonReflectMapWriter;
 import org.apache.solr.jersey.PermissionName;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
- * A V2 API that allows users to import an index constructed offline into a shard of their
- * collection
+ * V2 API implementation allowing users to import offline-constructed index into a shard.
  *
  * <p>Particularly useful for installing (per-shard) indices constructed offline into a SolrCloud
  * deployment. Callers are required to put the collection into read-only mode prior to installing
  * data into any shards of that collection, and should exit read only mode when completed.
  */
-@Path("/collections/{collName}/shards/{shardName}/install")
-public class InstallShardDataAPI extends AdminAPIBase {
-
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+public class InstallShardData extends AdminAPIBase implements InstallShardDataApi {
 
   @Inject
-  public InstallShardDataAPI(
+  public InstallShardData(
       CoreContainer coreContainer,
       SolrQueryRequest solrQueryRequest,
       SolrQueryResponse solrQueryResponse) {
     super(coreContainer, solrQueryRequest, solrQueryResponse);
   }
 
-  @POST
-  @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
   @PermissionName(COLL_EDIT_PERM)
   public SolrJerseyResponse installShardData(
-      @PathParam("collName") String collName,
-      @PathParam("shardName") String shardName,
-      InstallShardRequestBody requestBody)
-      throws Exception {
+      String collName, String shardName, InstallShardDataRequestBody requestBody) throws Exception {
     final SolrJerseyResponse response = instantiateJerseyResponse(SolrJerseyResponse.class);
     final CoreContainer coreContainer = fetchAndValidateZooKeeperAwareCoreContainer();
     recordCollectionForLogAndTracing(collName, solrQueryRequest);
@@ -130,28 +113,17 @@ public class InstallShardDataAPI extends AdminAPIBase {
   }
 
   public static ZkNodeProps createRemoteMessage(
-      String collectionName, String shardName, InstallShardRequestBody requestBody) {
+      String collectionName, String shardName, InstallShardDataRequestBody requestBody) {
     final InstallShardDataCmd.RemoteMessage messageTyped = new InstallShardDataCmd.RemoteMessage();
     messageTyped.collection = collectionName;
     messageTyped.shard = shardName;
     if (requestBody != null) {
       messageTyped.location = requestBody.location;
       messageTyped.repository = requestBody.repository;
-      messageTyped.asyncId = requestBody.asyncId;
+      messageTyped.asyncId = requestBody.async;
     }
 
     messageTyped.validate();
     return new ZkNodeProps(messageTyped.toMap(new HashMap<>()));
   }
-
-  public static class InstallShardRequestBody implements JacksonReflectMapWriter {
-    @JsonProperty(defaultValue = "location", required = true)
-    public String location;
-
-    @JsonProperty("repository")
-    public String repository;
-
-    @JsonProperty("async")
-    public String asyncId;
-  }
 }
diff --git a/solr/modules/gcs-repository/src/test/org/apache/solr/gcs/GCSInstallShardTest.java b/solr/modules/gcs-repository/src/test/org/apache/solr/gcs/GCSInstallShardTest.java
index 51dc59d2ea0..3d0d30262ed 100644
--- a/solr/modules/gcs-repository/src/test/org/apache/solr/gcs/GCSInstallShardTest.java
+++ b/solr/modules/gcs-repository/src/test/org/apache/solr/gcs/GCSInstallShardTest.java
@@ -20,6 +20,7 @@ package org.apache.solr.gcs;
 import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering;
 import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.solr.cloud.api.collections.AbstractInstallShardTest;
+import org.apache.solr.handler.admin.api.InstallShardData;
 import org.junit.AfterClass;
 import org.junit.BeforeClass;
 
@@ -27,7 +28,7 @@ import org.junit.BeforeClass;
  * Tests validating that the 'Install Shard API' works when used with {@link GCSBackupRepository}
  *
  * @see org.apache.solr.cloud.api.collections.AbstractInstallShardTest
- * @see org.apache.solr.handler.admin.api.InstallShardDataAPI
+ * @see InstallShardData
  */
 // Backups do checksum validation against a footer value not present in 'SimpleText'
 @LuceneTestCase.SuppressCodecs({"SimpleText"})
diff --git a/solr/modules/s3-repository/src/test/org/apache/solr/s3/S3InstallShardTest.java b/solr/modules/s3-repository/src/test/org/apache/solr/s3/S3InstallShardTest.java
index 189928f3dbb..ea21cb58877 100644
--- a/solr/modules/s3-repository/src/test/org/apache/solr/s3/S3InstallShardTest.java
+++ b/solr/modules/s3-repository/src/test/org/apache/solr/s3/S3InstallShardTest.java
@@ -21,6 +21,7 @@ import com.adobe.testing.s3mock.junit4.S3MockRule;
 import com.carrotsearch.randomizedtesting.annotations.ThreadLeakLingering;
 import org.apache.lucene.tests.util.LuceneTestCase;
 import org.apache.solr.cloud.api.collections.AbstractInstallShardTest;
+import org.apache.solr.handler.admin.api.InstallShardData;
 import org.junit.BeforeClass;
 import org.junit.ClassRule;
 import software.amazon.awssdk.regions.Region;
@@ -29,7 +30,7 @@ import software.amazon.awssdk.regions.Region;
  * Tests validating that the 'Install Shard API' works when used with {@link S3BackupRepository}
  *
  * @see org.apache.solr.cloud.api.collections.AbstractInstallShardTest
- * @see org.apache.solr.handler.admin.api.InstallShardDataAPI
+ * @see InstallShardData
  */
 // Backups do checksum validation against a footer value not present in 'SimpleText'
 @LuceneTestCase.SuppressCodecs({"SimpleText"})
diff --git a/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractInstallShardTest.java b/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractInstallShardTest.java
index 70f1a38e18e..cc9d655f04c 100644
--- a/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractInstallShardTest.java
+++ b/solr/test-framework/src/java/org/apache/solr/cloud/api/collections/AbstractInstallShardTest.java
@@ -48,6 +48,7 @@ import org.apache.solr.core.CoreDescriptor;
 import org.apache.solr.core.DirectoryFactory;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.backup.repository.BackupRepository;
+import org.apache.solr.handler.admin.api.InstallShardData;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.BeforeClass;
@@ -62,7 +63,7 @@ import org.slf4j.LoggerFactory;
  * repository. This base-class will populate that backup repository all data necessary for these
  * tests.
  *
- * @see org.apache.solr.handler.admin.api.InstallShardDataAPI
+ * @see InstallShardData
  */
 public abstract class AbstractInstallShardTest extends SolrCloudTestCase {
 


[solr] 05/06: Migrade install-core-data to 'api' module

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

gerlowskija pushed a commit to branch SOLR-16825-migrate-definitions-to-api-module-pt4
in repository https://gitbox.apache.org/repos/asf/solr.git

commit 1896fdde26b74e61292475629bf09274521e97e1
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Wed Sep 27 10:33:46 2023 -0400

    Migrade install-core-data to 'api' module
---
 .../client/api/endpoint/InstallCoreDataApi.java    | 42 ++++++++++++++++++++++
 .../api/model/InstallCoreDataRequestBody.java      | 30 ++++++++++++++++
 .../solr/handler/admin/CoreAdminHandler.java       |  4 +--
 .../solr/handler/admin/InstallCoreDataOp.java      | 12 +++----
 ...nstallCoreDataAPI.java => InstallCoreData.java} | 40 ++++-----------------
 5 files changed, 86 insertions(+), 42 deletions(-)

diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/InstallCoreDataApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/InstallCoreDataApi.java
new file mode 100644
index 00000000000..4ee95539571
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/InstallCoreDataApi.java
@@ -0,0 +1,42 @@
+/*
+ * 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 io.swagger.v3.oas.annotations.Operation;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import org.apache.solr.client.api.model.InstallCoreDataRequestBody;
+import org.apache.solr.client.api.model.SolrJerseyResponse;
+
+/**
+ * V2 API definition for installing an offline index to a single core of a shard.
+ *
+ * <p>This is an internal API intended for use only by the Collection Admin "Install Shard Data"
+ * API.
+ */
+@Path("/cores/{coreName}/install")
+public interface InstallCoreDataApi {
+
+  @POST
+  @Operation(
+      summary = "Install an offline index to a specified core",
+      tags = {"cores"})
+  SolrJerseyResponse installCoreData(
+      @PathParam("coreName") String coreName, InstallCoreDataRequestBody requestBody)
+      throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/InstallCoreDataRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/InstallCoreDataRequestBody.java
new file mode 100644
index 00000000000..2ba9d09c1f6
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/InstallCoreDataRequestBody.java
@@ -0,0 +1,30 @@
+/*
+ * 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 InstallCoreDataRequestBody {
+  // Expected to point to an index directory (e.g. data/techproducts_shard1_replica_n1/data/index)
+  // for a single core that has previously been uploaded to the backup repository previously
+  // uploaded to the backup repository.
+  @JsonProperty public String location;
+
+  @JsonProperty public String repository;
+
+  @JsonProperty public String asyncId;
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
index d928282df5c..d9ece272f75 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
@@ -58,7 +58,7 @@ import org.apache.solr.handler.admin.api.AllCoresStatusAPI;
 import org.apache.solr.handler.admin.api.BackupCoreAPI;
 import org.apache.solr.handler.admin.api.CoreSnapshotAPI;
 import org.apache.solr.handler.admin.api.CreateCoreAPI;
-import org.apache.solr.handler.admin.api.InstallCoreDataAPI;
+import org.apache.solr.handler.admin.api.InstallCoreData;
 import org.apache.solr.handler.admin.api.MergeIndexesAPI;
 import org.apache.solr.handler.admin.api.OverseerOperationAPI;
 import org.apache.solr.handler.admin.api.PrepareCoreRecoveryAPI;
@@ -403,7 +403,7 @@ public class CoreAdminHandler extends RequestHandlerBase implements PermissionNa
   public Collection<Class<? extends JerseyResource>> getJerseyResources() {
     return List.of(
         CoreSnapshotAPI.class,
-        InstallCoreDataAPI.class,
+        InstallCoreData.class,
         BackupCoreAPI.class,
         RestoreCoreAPI.class,
         ReloadCoreAPI.class);
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/InstallCoreDataOp.java b/solr/core/src/java/org/apache/solr/handler/admin/InstallCoreDataOp.java
index c115739f6a8..7d7ada266a3 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/InstallCoreDataOp.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/InstallCoreDataOp.java
@@ -21,9 +21,10 @@ import static org.apache.solr.common.params.CommonAdminParams.ASYNC;
 import static org.apache.solr.common.params.CoreAdminParams.BACKUP_LOCATION;
 import static org.apache.solr.common.params.CoreAdminParams.BACKUP_REPOSITORY;
 
+import org.apache.solr.client.api.model.InstallCoreDataRequestBody;
 import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.handler.admin.api.InstallCoreDataAPI;
+import org.apache.solr.handler.admin.api.InstallCoreData;
 import org.apache.solr.handler.api.V2ApiUtils;
 
 /**
@@ -31,7 +32,7 @@ import org.apache.solr.handler.api.V2ApiUtils;
  * "Install Shard Data" Collection-Admin functionality
  *
  * <p>Converts v1-style query parameters into a v2-style request body and delegating to {@link
- * InstallCoreDataAPI}.
+ * InstallCoreData}.
  */
 public class InstallCoreDataOp implements CoreAdminHandler.CoreAdminOp {
   @Override
@@ -39,11 +40,10 @@ public class InstallCoreDataOp implements CoreAdminHandler.CoreAdminOp {
     final SolrParams params = it.req.getParams();
     final String coreName = params.required().get(CoreAdminParams.CORE);
 
-    final InstallCoreDataAPI api =
-        new InstallCoreDataAPI(
+    final InstallCoreData api =
+        new InstallCoreData(
             it.handler.getCoreContainer(), it.handler.getCoreAdminAsyncTracker(), it.req, it.rsp);
-    final InstallCoreDataAPI.InstallCoreDataRequestBody requestBody =
-        new InstallCoreDataAPI.InstallCoreDataRequestBody();
+    final InstallCoreDataRequestBody requestBody = new InstallCoreDataRequestBody();
     requestBody.repository = params.get(BACKUP_REPOSITORY);
     requestBody.location = params.get(BACKUP_LOCATION);
     requestBody.asyncId = params.get(ASYNC);
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/InstallCoreDataAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/InstallCoreData.java
similarity index 73%
rename from solr/core/src/java/org/apache/solr/handler/admin/api/InstallCoreDataAPI.java
rename to solr/core/src/java/org/apache/solr/handler/admin/api/InstallCoreData.java
index c0cd11b3451..a64fff77905 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/InstallCoreDataAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/InstallCoreData.java
@@ -17,16 +17,11 @@
 
 package org.apache.solr.handler.admin.api;
 
-import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
 import static org.apache.solr.security.PermissionNameProvider.Name.CORE_EDIT_PERM;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
-import java.lang.invoke.MethodHandles;
 import java.net.URI;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-import javax.ws.rs.Produces;
+import org.apache.solr.client.api.endpoint.InstallCoreDataApi;
+import org.apache.solr.client.api.model.InstallCoreDataRequestBody;
 import org.apache.solr.client.api.model.SolrJerseyResponse;
 import org.apache.solr.cloud.CloudDescriptor;
 import org.apache.solr.cloud.ZkController;
@@ -36,25 +31,19 @@ import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.backup.repository.BackupRepository;
 import org.apache.solr.handler.RestoreCore;
 import org.apache.solr.handler.admin.CoreAdminHandler;
-import org.apache.solr.jersey.JacksonReflectMapWriter;
 import org.apache.solr.jersey.PermissionName;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
- * v2 implementation of the "Install Core Data" Core-Admin API
+ * V2 API implementation of the "Install Core Data" Core-Admin API
  *
  * <p>This is an internal API intended for use only by the Collection Admin "Install Shard Data"
  * API.
  */
-@Path("/cores/{coreName}/install")
-public class InstallCoreDataAPI extends CoreAdminAPIBase {
+public class InstallCoreData extends CoreAdminAPIBase implements InstallCoreDataApi {
 
-  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
-  public InstallCoreDataAPI(
+  public InstallCoreData(
       CoreContainer coreContainer,
       CoreAdminHandler.CoreAdminAsyncTracker coreAdminAsyncTracker,
       SolrQueryRequest req,
@@ -62,11 +51,8 @@ public class InstallCoreDataAPI extends CoreAdminAPIBase {
     super(coreContainer, coreAdminAsyncTracker, req, rsp);
   }
 
-  @POST
-  @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
   @PermissionName(CORE_EDIT_PERM)
-  public SolrJerseyResponse installCoreData(
-      @PathParam("coreName") String coreName, InstallCoreDataRequestBody requestBody)
+  public SolrJerseyResponse installCoreData(String coreName, InstallCoreDataRequestBody requestBody)
       throws Exception {
     final SolrJerseyResponse response = instantiateJerseyResponse(SolrJerseyResponse.class);
 
@@ -118,18 +104,4 @@ public class InstallCoreDataAPI extends CoreAdminAPIBase {
 
     return response;
   }
-
-  public static class InstallCoreDataRequestBody implements JacksonReflectMapWriter {
-    // Expected to point to an index directory (e.g. data/techproducts_shard1_replica_n1/data/index)
-    // for a single core that has previously been uploaded to the backup repository previously
-    // uploaded to the backup repository.
-    @JsonProperty("location")
-    public String location;
-
-    @JsonProperty("repository")
-    public String repository;
-
-    @JsonProperty("async")
-    public String asyncId;
-  }
 }