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/06/27 19:38:24 UTC

[solr] 01/02: SOLR-16395 JAX-RS conversion for remaining GET /schema/* endpoints (#1682)

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

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

commit 968504d0818b30e162e4c420908438bbdf311760
Author: bszabo97 <79...@users.noreply.github.com>
AuthorDate: Sat Jun 17 21:44:17 2023 +0200

    SOLR-16395 JAX-RS conversion for remaining GET /schema/* endpoints (#1682)
    
    Migrates several v2 `GET /schema` APIs from the legacy annotation framework
    to JAX-RS, including:
        - `/zkversion` - lookup the version of the schema in ZK
        - `/schema/fields` - list the (non-dynamic) fields in the schema
        - `/schema/fields/fName` - information about a particular (non-dynamic)
           field in the schema
        - `/schema/dynamicfields` - list the (dynamic) fields in the schema
        - `/schema/dynamicfields/fName` - information about a particular (dynamic)
           field in the schema
        - `/schema/fieldtypes` - list the field types in the schema
        - `/schema/fieldtypes/tName` - information about a particular fieldtype in
            the schema
        - `/schema/copyfields` - list the copyfields in the schema
    
    
    This change doesn't modify the APIs themselves, so users should remain unaffected.
---
 .../org/apache/solr/handler/SchemaHandler.java     | 172 +++++-------
 .../solr/handler/admin/api/GetSchemaAPI.java       |  22 +-
 .../solr/handler/admin/api/GetSchemaFieldAPI.java  | 298 +++++++++++++++++++++
 .../handler/admin/api/GetSchemaZkVersionAPI.java   |  86 ++++++
 .../admin/api/SchemaGetDynamicFieldAPI.java        |  48 ----
 .../solr/handler/admin/api/SchemaGetFieldAPI.java  |  48 ----
 .../handler/admin/api/SchemaGetFieldTypeAPI.java   |  48 ----
 .../admin/api/SchemaListAllCopyFieldsAPI.java      |  48 ----
 .../admin/api/SchemaListAllDynamicFieldsAPI.java   |  48 ----
 .../admin/api/SchemaListAllFieldTypesAPI.java      |  48 ----
 .../handler/admin/api/SchemaListAllFieldsAPI.java  |  48 ----
 .../solr/handler/admin/api/SchemaNameAPI.java      |  70 -----
 .../solr/handler/admin/api/SchemaZkVersionAPI.java |  48 ----
 .../org/apache/solr/jersey/InjectionFactories.java |  20 ++
 .../org/apache/solr/jersey/JerseyApplications.java |   4 +
 .../org/apache/solr/api/JerseyResourceTest.java    |  10 +-
 .../solr/handler/admin/api/GetSchemaAPITest.java   |  36 +++
 .../handler/admin/api/GetSchemaFieldsAPITest.java  | 148 ++++++++++
 .../admin/api/GetSchemaZkVersionAPITest.java       |  54 ++++
 .../solr/handler/admin/api/SchemaNameAPITest.java  |  85 ------
 .../handler/admin/api/V2SchemaAPIMappingTest.java  |  20 --
 21 files changed, 736 insertions(+), 673 deletions(-)

diff --git a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
index 89dc0ffd3de..58a2ad1890a 100644
--- a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
@@ -36,38 +36,21 @@ import org.apache.solr.api.AnnotatedApi;
 import org.apache.solr.api.Api;
 import org.apache.solr.api.ApiBag;
 import org.apache.solr.api.JerseyResource;
-import org.apache.solr.cloud.ZkSolrResourceLoader;
-import org.apache.solr.common.MapWriter;
 import org.apache.solr.common.SolrException;
-import org.apache.solr.common.cloud.SolrClassLoader;
 import org.apache.solr.common.params.MapSolrParams;
 import org.apache.solr.common.params.SolrParams;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.common.util.StrUtils;
-import org.apache.solr.core.PluginInfo;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.handler.admin.api.GetSchemaAPI;
+import org.apache.solr.handler.admin.api.GetSchemaFieldAPI;
+import org.apache.solr.handler.admin.api.GetSchemaZkVersionAPI;
 import org.apache.solr.handler.admin.api.SchemaBulkModifyAPI;
-import org.apache.solr.handler.admin.api.SchemaGetDynamicFieldAPI;
-import org.apache.solr.handler.admin.api.SchemaGetFieldAPI;
-import org.apache.solr.handler.admin.api.SchemaGetFieldTypeAPI;
-import org.apache.solr.handler.admin.api.SchemaListAllCopyFieldsAPI;
-import org.apache.solr.handler.admin.api.SchemaListAllDynamicFieldsAPI;
-import org.apache.solr.handler.admin.api.SchemaListAllFieldTypesAPI;
-import org.apache.solr.handler.admin.api.SchemaListAllFieldsAPI;
-import org.apache.solr.handler.admin.api.SchemaNameAPI;
-import org.apache.solr.handler.admin.api.SchemaZkVersionAPI;
 import org.apache.solr.handler.api.V2ApiUtils;
-import org.apache.solr.pkg.PackageListeningClassLoader;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestHandler;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.rest.RestManager;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.ManagedIndexSchema;
 import org.apache.solr.schema.SchemaManager;
-import org.apache.solr.schema.ZkIndexSchemaReader;
 import org.apache.solr.security.AuthorizationContext;
 import org.apache.solr.security.PermissionNameProvider;
 import org.apache.solr.util.plugin.SolrCoreAware;
@@ -163,31 +146,15 @@ public class SchemaHandler extends RequestHandlerBase
         case "/schema/name":
           {
             V2ApiUtils.squashIntoSolrResponseWithoutHeader(
-                rsp, new SchemaNameAPI(req.getCore()).getSchemaName());
+                rsp, new GetSchemaAPI(req.getCore().getLatestSchema()).getSchemaName());
             break;
           }
         case "/schema/zkversion":
           {
-            int refreshIfBelowVersion = req.getParams().getInt("refreshIfBelowVersion", -1);
-            int zkVersion = -1;
-            IndexSchema schema = req.getSchema();
-            if (schema instanceof ManagedIndexSchema) {
-              ManagedIndexSchema managed = (ManagedIndexSchema) schema;
-              zkVersion = managed.getSchemaZkVersion();
-              if (refreshIfBelowVersion != -1 && zkVersion < refreshIfBelowVersion) {
-                log.info(
-                    "REFRESHING SCHEMA (refreshIfBelowVersion={}, currentVersion={}) before returning version!",
-                    refreshIfBelowVersion,
-                    zkVersion);
-                ZkSolrResourceLoader zkSolrResourceLoader =
-                    (ZkSolrResourceLoader) req.getCore().getResourceLoader();
-                ZkIndexSchemaReader zkIndexSchemaReader =
-                    zkSolrResourceLoader.getZkIndexSchemaReader();
-                managed = zkIndexSchemaReader.refreshSchemaFromZk(refreshIfBelowVersion);
-                zkVersion = managed.getSchemaZkVersion();
-              }
-            }
-            rsp.add("zkversion", zkVersion);
+            V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                rsp,
+                new GetSchemaZkVersionAPI(req.getCore())
+                    .getSchemaZkVersion(req.getParams().getInt("refreshIfBelowVersion", -1)));
             break;
           }
         default:
@@ -195,7 +162,6 @@ public class SchemaHandler extends RequestHandlerBase
             List<String> parts = StrUtils.splitSmart(path, '/', true);
             if (parts.size() > 1 && level2.containsKey(parts.get(1))) {
               String realName = parts.get(1);
-              String fieldName = IndexSchema.nameMapping.get(realName);
 
               String pathParam = level2.get(realName); // Might be null
               if (parts.size() > 2) {
@@ -203,32 +169,66 @@ public class SchemaHandler extends RequestHandlerBase
                     SolrParams.wrapDefaults(
                         new MapSolrParams(singletonMap(pathParam, parts.get(2))), req.getParams()));
               }
-              Map<String, Object> propertyValues =
-                  req.getSchema().getNamedPropertyValues(realName, req.getParams());
-              Object o = propertyValues.get(fieldName);
-              if (parts.size() > 2) {
-                String name = parts.get(2);
-                if (o instanceof List) {
-                  List<?> list = (List<?>) o;
-                  for (Object obj : list) {
-                    if (obj instanceof SimpleOrderedMap) {
-                      SimpleOrderedMap<?> simpleOrderedMap = (SimpleOrderedMap<?>) obj;
-                      if (name.equals(simpleOrderedMap.get("name"))) {
-                        rsp.add(fieldName.substring(0, realName.length() - 1), simpleOrderedMap);
-                        insertPackageInfo(rsp.getValues(), req);
-                        return;
-                      }
+              switch (realName) {
+                case "fields":
+                  {
+                    if (parts.size() > 2) {
+                      V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                          rsp,
+                          new GetSchemaFieldAPI(req.getCore().getLatestSchema(), req.getParams())
+                              .getFieldInfo(parts.get(2)));
+                    } else {
+                      V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                          rsp,
+                          new GetSchemaFieldAPI(req.getCore().getLatestSchema(), req.getParams())
+                              .listSchemaFields());
+                    }
+                    return;
+                  }
+                case "copyfields":
+                  {
+                    V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                        rsp,
+                        new GetSchemaFieldAPI(req.getCore().getLatestSchema(), req.getParams())
+                            .listCopyFields());
+                    return;
+                  }
+                case "dynamicfields":
+                  {
+                    if (parts.size() > 2) {
+                      V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                          rsp,
+                          new GetSchemaFieldAPI(req.getCore().getLatestSchema(), req.getParams())
+                              .getDynamicFieldInfo(parts.get(2)));
+                    } else {
+                      V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                          rsp,
+                          new GetSchemaFieldAPI(req.getCore().getLatestSchema(), req.getParams())
+                              .listDynamicFields());
+                    }
+                    return;
+                  }
+                case "fieldtypes":
+                  {
+                    if (parts.size() > 2) {
+                      V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                          rsp,
+                          new GetSchemaFieldAPI(req.getCore().getLatestSchema(), req.getParams())
+                              .getFieldTypeInfo(parts.get(2)));
+                    } else {
+                      V2ApiUtils.squashIntoSolrResponseWithoutHeader(
+                          rsp,
+                          new GetSchemaFieldAPI(req.getCore().getLatestSchema(), req.getParams())
+                              .listSchemaFieldTypes());
                     }
+                    return;
+                  }
+                default:
+                  {
+                    break;
                   }
-                }
-                throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "No such path " + path);
-              } else {
-                rsp.add(fieldName, o);
               }
-              insertPackageInfo(rsp.getValues(), req);
-              return;
             }
-
             throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "No such path " + path);
           }
       }
@@ -238,42 +238,6 @@ public class SchemaHandler extends RequestHandlerBase
     }
   }
 
-  /**
-   * If a plugin is loaded from a package, the version of the package being used should be added to
-   * the response
-   */
-  private void insertPackageInfo(Object o, SolrQueryRequest req) {
-    if (!req.getParams().getBool("meta", false)) return;
-    if (o instanceof List) {
-      List<?> l = (List<?>) o;
-      for (Object o1 : l) {
-        if (o1 instanceof NamedList || o1 instanceof List) insertPackageInfo(o1, req);
-      }
-
-    } else if (o instanceof NamedList) {
-      @SuppressWarnings("unchecked")
-      NamedList<Object> nl = (NamedList<Object>) o;
-      nl.forEach(
-          (n, v) -> {
-            if (v instanceof NamedList || v instanceof List) insertPackageInfo(v, req);
-          });
-      Object v = nl.get("class");
-      if (v instanceof String) {
-        String klas = (String) v;
-        PluginInfo.ClassName parsedClassName = new PluginInfo.ClassName(klas);
-        if (parsedClassName.pkg != null) {
-          SolrClassLoader solrClassLoader = req.getCore().getLatestSchema().getSolrClassLoader();
-          MapWriter mw =
-              solrClassLoader instanceof PackageListeningClassLoader
-                  ? ((PackageListeningClassLoader) solrClassLoader)
-                      .getPackageVersion(parsedClassName)
-                  : null;
-          if (mw != null) nl.add("_packageinfo_", mw);
-        }
-      }
-    }
-  }
-
   private static final Set<String> subPaths =
       new HashSet<>(
           Set.of(
@@ -320,14 +284,6 @@ public class SchemaHandler extends RequestHandlerBase
   public Collection<Api> getApis() {
 
     final List<Api> apis = new ArrayList<>();
-    apis.addAll(AnnotatedApi.getApis(new SchemaZkVersionAPI(this)));
-    apis.addAll(AnnotatedApi.getApis(new SchemaListAllFieldsAPI(this)));
-    apis.addAll(AnnotatedApi.getApis(new SchemaGetFieldAPI(this)));
-    apis.addAll(AnnotatedApi.getApis(new SchemaListAllCopyFieldsAPI(this)));
-    apis.addAll(AnnotatedApi.getApis(new SchemaListAllDynamicFieldsAPI(this)));
-    apis.addAll(AnnotatedApi.getApis(new SchemaGetDynamicFieldAPI(this)));
-    apis.addAll(AnnotatedApi.getApis(new SchemaListAllFieldTypesAPI(this)));
-    apis.addAll(AnnotatedApi.getApis(new SchemaGetFieldTypeAPI(this)));
     apis.addAll(AnnotatedApi.getApis(new SchemaBulkModifyAPI(this)));
 
     return apis;
@@ -335,7 +291,7 @@ public class SchemaHandler extends RequestHandlerBase
 
   @Override
   public Collection<Class<? extends JerseyResource>> getJerseyResources() {
-    return List.of(SchemaNameAPI.class, GetSchemaAPI.class);
+    return List.of(GetSchemaAPI.class, GetSchemaFieldAPI.class, GetSchemaZkVersionAPI.class);
   }
 
   @Override
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaAPI.java
index 461120aab15..3a966866727 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaAPI.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaAPI.java
@@ -27,6 +27,7 @@ import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
 import javax.ws.rs.core.MediaType;
 import org.apache.solr.api.JerseyResource;
+import org.apache.solr.common.SolrException;
 import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.jersey.PermissionName;
 import org.apache.solr.jersey.SolrJerseyResponse;
@@ -36,7 +37,7 @@ import org.apache.solr.security.PermissionNameProvider;
 @Path("/{a:cores|collections}/{collectionName}/schema")
 public class GetSchemaAPI extends JerseyResource {
 
-  private IndexSchema indexSchema;
+  protected final IndexSchema indexSchema;
 
   @Inject
   public GetSchemaAPI(IndexSchema indexSchema) {
@@ -63,6 +64,25 @@ public class GetSchemaAPI extends JerseyResource {
     public Map<String, Object> schema;
   }
 
+  @GET
+  @Path("/name")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaNameResponse getSchemaName() throws Exception {
+    final SchemaNameResponse response = instantiateJerseyResponse(SchemaNameResponse.class);
+    if (null == indexSchema.getSchemaName()) {
+      throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "Schema has no name");
+    }
+
+    response.name = indexSchema.getSchemaName();
+    return response;
+  }
+
+  public static class SchemaNameResponse extends SolrJerseyResponse {
+    @JsonProperty("name")
+    public String name;
+  }
+
   @GET
   @Path("/similarity")
   @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, BINARY_CONTENT_TYPE_V2})
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaFieldAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaFieldAPI.java
new file mode 100644
index 00000000000..b5c3fbbb2a7
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaFieldAPI.java
@@ -0,0 +1,298 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+import java.util.Map;
+import javax.inject.Inject;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+import org.apache.solr.common.MapWriter;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.cloud.SolrClassLoader;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.core.PluginInfo;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.pkg.PackageListeningClassLoader;
+import org.apache.solr.schema.IndexSchema;
+import org.apache.solr.security.PermissionNameProvider;
+
+/**
+ * <code>GetSchemaFieldAPI</code> contains the V2 APIs for all field related endpoint which are
+ *
+ * <ul>
+ *   <li>/fields
+ *   <li>/fields/{fieldName}
+ *   <li>/copyfields
+ *   <li>/dynamicfields
+ *   <li>/dynamicfields/{fieldName}
+ *   <li>/fieldtypes
+ *   <li>/fieldtypes/{fieldTypeName}
+ * </ul>
+ */
+public class GetSchemaFieldAPI extends GetSchemaAPI {
+
+  private final SolrParams params;
+
+  // TODO Stop using SolrParams here and instead give API methods parameters representing only those
+  // query-params that they support
+  @Inject
+  public GetSchemaFieldAPI(IndexSchema indexSchema, SolrParams params) {
+    super(indexSchema);
+    this.params = params;
+  }
+
+  @GET
+  @Path("/fields")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaListFieldsResponse listSchemaFields() {
+    SchemaListFieldsResponse response = instantiateJerseyResponse(SchemaListFieldsResponse.class);
+    final String realName = "fields";
+
+    response.fields = listAllFieldsOfType(realName, params);
+
+    return response;
+  }
+
+  public static class SchemaListFieldsResponse extends SolrJerseyResponse {
+    @JsonProperty("fields")
+    public List<Object> fields;
+  }
+
+  @GET
+  @Path("/fields/{fieldName}")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaGetFieldInfoResponse getFieldInfo(@PathParam("fieldName") String fieldName) {
+    if (fieldName == null) {
+      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "Field name must not be null");
+    }
+    SchemaGetFieldInfoResponse response =
+        instantiateJerseyResponse(SchemaGetFieldInfoResponse.class);
+    final String realName = "fields";
+
+    SimpleOrderedMap<Object> fieldInfo = retrieveFieldInfoOfType(realName, fieldName, params);
+    if (fieldInfo != null) {
+      response.fieldInfo = fieldInfo;
+      return response;
+    }
+    throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "No such field [" + fieldName + "]");
+  }
+
+  public static class SchemaGetFieldInfoResponse extends SolrJerseyResponse {
+    @JsonProperty("field")
+    public SimpleOrderedMap<?> fieldInfo;
+  }
+
+  @GET
+  @Path("/copyfields")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaListCopyFieldsResponse listCopyFields() {
+    SchemaListCopyFieldsResponse response =
+        instantiateJerseyResponse(SchemaListCopyFieldsResponse.class);
+    final String realName = "copyfields";
+
+    response.copyFields = listAllFieldsOfType(realName, params);
+
+    return response;
+  }
+
+  public static class SchemaListCopyFieldsResponse extends SolrJerseyResponse {
+    @JsonProperty("copyFields")
+    public List<Object> copyFields;
+  }
+
+  @GET
+  @Path("/dynamicfields")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaListDynamicFieldsResponse listDynamicFields() {
+    SchemaListDynamicFieldsResponse response =
+        instantiateJerseyResponse(SchemaListDynamicFieldsResponse.class);
+    final String realName = "dynamicfields";
+
+    response.dynamicFields = listAllFieldsOfType(realName, params);
+
+    return response;
+  }
+
+  public static class SchemaListDynamicFieldsResponse extends SolrJerseyResponse {
+    @JsonProperty("dynamicFields")
+    public List<Object> dynamicFields;
+  }
+
+  @GET
+  @Path("/dynamicfields/{fieldName}")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaGetDynamicFieldInfoResponse getDynamicFieldInfo(
+      @PathParam("fieldName") String fieldName) {
+    if (fieldName == null) {
+      throw new SolrException(
+          SolrException.ErrorCode.BAD_REQUEST, "Dynamic field name must not be null");
+    }
+    SchemaGetDynamicFieldInfoResponse response =
+        instantiateJerseyResponse(SchemaGetDynamicFieldInfoResponse.class);
+    final String realName = "dynamicfields";
+
+    SimpleOrderedMap<Object> dynamicFieldInfo =
+        retrieveFieldInfoOfType(realName, fieldName, params);
+    if (dynamicFieldInfo != null) {
+      response.dynamicFieldInfo = dynamicFieldInfo;
+      return response;
+    }
+    throw new SolrException(
+        SolrException.ErrorCode.NOT_FOUND, "No such dynamic field [" + fieldName + "]");
+  }
+
+  public static class SchemaGetDynamicFieldInfoResponse extends SolrJerseyResponse {
+    @JsonProperty("dynamicField")
+    public SimpleOrderedMap<?> dynamicFieldInfo;
+  }
+
+  @GET
+  @Path("/fieldtypes")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaListFieldTypesResponse listSchemaFieldTypes() {
+    SchemaListFieldTypesResponse response =
+        instantiateJerseyResponse(SchemaListFieldTypesResponse.class);
+    final String realName = "fieldtypes";
+
+    response.fieldTypes = listAllFieldsOfType(realName, params);
+
+    return response;
+  }
+
+  public static class SchemaListFieldTypesResponse extends SolrJerseyResponse {
+    @JsonProperty("fieldTypes")
+    public List<Object> fieldTypes;
+  }
+
+  @GET
+  @Path("/fieldtypes/{fieldTypeName}")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaGetFieldTypeInfoResponse getFieldTypeInfo(
+      @PathParam("fieldTypeName") String fieldTypeName) {
+    if (fieldTypeName == null) {
+      throw new SolrException(
+          SolrException.ErrorCode.BAD_REQUEST, "Field type name must not be null");
+    }
+    SchemaGetFieldTypeInfoResponse response =
+        instantiateJerseyResponse(SchemaGetFieldTypeInfoResponse.class);
+
+    final String realName = "fieldtypes";
+
+    SimpleOrderedMap<Object> fieldTypeInfo =
+        retrieveFieldInfoOfType(realName, fieldTypeName, params);
+    if (fieldTypeInfo != null) {
+      response.fieldTypeInfo = fieldTypeInfo;
+      return response;
+    }
+    throw new SolrException(
+        SolrException.ErrorCode.NOT_FOUND, "No such field type [" + fieldTypeName + "]");
+  }
+
+  public static class SchemaGetFieldTypeInfoResponse extends SolrJerseyResponse {
+    @JsonProperty("fieldType")
+    public SimpleOrderedMap<?> fieldTypeInfo;
+  }
+
+  private List<Object> listAllFieldsOfType(String realName, SolrParams params) {
+    String camelCaseRealName = IndexSchema.nameMapping.get(realName);
+    Map<String, Object> propertyValues = indexSchema.getNamedPropertyValues(realName, params);
+    @SuppressWarnings("unchecked")
+    List<Object> list = (List<Object>) propertyValues.get(camelCaseRealName);
+    if (params.getBool("meta", false)) {
+      insertPackageInfo(list);
+    }
+    return list;
+  }
+
+  @SuppressWarnings("unchecked")
+  private SimpleOrderedMap<Object> retrieveFieldInfoOfType(
+      String realName, String fieldName, SolrParams params) {
+    SimpleOrderedMap<Object> returnFieldInfo = null;
+    String camelCaseRealName = IndexSchema.nameMapping.get(realName);
+    Map<String, Object> propertyValues = indexSchema.getNamedPropertyValues(realName, params);
+    Object o = propertyValues.get(camelCaseRealName);
+    if (o instanceof List) {
+      List<?> list = (List<?>) o;
+      for (Object obj : list) {
+        if (obj instanceof SimpleOrderedMap) {
+          SimpleOrderedMap<Object> fieldInfo = (SimpleOrderedMap<Object>) obj;
+          if (fieldName.equals(fieldInfo.get("name"))) {
+            returnFieldInfo = fieldInfo;
+            if (params.getBool("meta", false)) {
+              insertPackageInfo(returnFieldInfo);
+            }
+            break;
+          }
+        }
+      }
+    }
+    return returnFieldInfo;
+  }
+
+  /**
+   * If a plugin is loaded from a package, the version of the package being used should be added to
+   * the response
+   */
+  private void insertPackageInfo(Object o) {
+    if (o instanceof List) {
+      List<?> l = (List<?>) o;
+      for (Object o1 : l) {
+        if (o1 instanceof NamedList || o1 instanceof List) insertPackageInfo(o1);
+      }
+
+    } else if (o instanceof NamedList) {
+      @SuppressWarnings("unchecked")
+      NamedList<Object> nl = (NamedList<Object>) o;
+      nl.forEach(
+          (n, v) -> {
+            if (v instanceof NamedList || v instanceof List) insertPackageInfo(v);
+          });
+      Object v = nl.get("class");
+      if (v instanceof String) {
+        String klas = (String) v;
+        PluginInfo.ClassName parsedClassName = new PluginInfo.ClassName(klas);
+        if (parsedClassName.pkg != null) {
+          SolrClassLoader solrClassLoader = indexSchema.getSolrClassLoader();
+          MapWriter mw =
+              solrClassLoader instanceof PackageListeningClassLoader
+                  ? ((PackageListeningClassLoader) solrClassLoader)
+                      .getPackageVersion(parsedClassName)
+                  : null;
+          if (mw != null) nl.add("_packageinfo_", mw);
+        }
+      }
+    }
+  }
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaZkVersionAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaZkVersionAPI.java
new file mode 100644
index 00000000000..56a22f77783
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/GetSchemaZkVersionAPI.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.lang.invoke.MethodHandles;
+import javax.inject.Inject;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import org.apache.solr.api.JerseyResource;
+import org.apache.solr.cloud.ZkSolrResourceLoader;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.jersey.PermissionName;
+import org.apache.solr.jersey.SolrJerseyResponse;
+import org.apache.solr.schema.ManagedIndexSchema;
+import org.apache.solr.schema.ZkIndexSchemaReader;
+import org.apache.solr.security.PermissionNameProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Path("/{a:cores|collections}/{collectionName}/schema")
+public class GetSchemaZkVersionAPI extends JerseyResource {
+
+  private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
+  private SolrCore solrCore;
+
+  @Inject
+  public GetSchemaZkVersionAPI(SolrCore solrCore) {
+    this.solrCore = solrCore;
+  }
+
+  @GET
+  @Path("/zkversion")
+  @Produces({MediaType.APPLICATION_JSON, MediaType.APPLICATION_ATOM_XML, BINARY_CONTENT_TYPE_V2})
+  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
+  public SchemaZkVersionResponse getSchemaZkVersion(
+      @DefaultValue("-1") @QueryParam("refreshIfBelowVersion") Integer refreshIfBelowVersion)
+      throws Exception {
+    final SchemaZkVersionResponse response =
+        instantiateJerseyResponse(SchemaZkVersionResponse.class);
+    int zkVersion = -1;
+    if (solrCore.getLatestSchema() instanceof ManagedIndexSchema) {
+      ManagedIndexSchema managed = (ManagedIndexSchema) solrCore.getLatestSchema();
+      zkVersion = managed.getSchemaZkVersion();
+      if (refreshIfBelowVersion != -1 && zkVersion < refreshIfBelowVersion) {
+        log.info(
+            "REFRESHING SCHEMA (refreshIfBelowVersion={}, currentVersion={}) before returning version!",
+            refreshIfBelowVersion,
+            zkVersion);
+        ZkSolrResourceLoader zkSolrResourceLoader =
+            (ZkSolrResourceLoader) solrCore.getResourceLoader();
+        ZkIndexSchemaReader zkIndexSchemaReader = zkSolrResourceLoader.getZkIndexSchemaReader();
+        managed = zkIndexSchemaReader.refreshSchemaFromZk(refreshIfBelowVersion);
+        zkVersion = managed.getSchemaZkVersion();
+      }
+    }
+    response.zkversion = zkVersion;
+    return response;
+  }
+
+  public static class SchemaZkVersionResponse extends SolrJerseyResponse {
+    @JsonProperty("zkversion")
+    public int zkversion;
+  }
+}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetDynamicFieldAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetDynamicFieldAPI.java
deleted file mode 100644
index 646540c4d67..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetDynamicFieldAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API for getting information about a single dynamic field definition from an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/dynamicfields/fieldName) is analogous to
- * the v1 /solr/collectionName/schema/dynamicfields/fieldName API.
- */
-public class SchemaGetDynamicFieldAPI {
-  private final SchemaHandler schemaHandler;
-
-  public SchemaGetDynamicFieldAPI(SchemaHandler schemaHandler) {
-    this.schemaHandler = schemaHandler;
-  }
-
-  @EndPoint(
-      path = {"/schema/dynamicfields/{name}"},
-      method = GET,
-      permission = PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public void getSingleDynamicField(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    schemaHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetFieldAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetFieldAPI.java
deleted file mode 100644
index a8a0798f1b6..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetFieldAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API to retrieve information about a single field from an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/field/fieldName) is analogous to the v1
- * /solr/collectionName/schema/fields/fieldName API.
- */
-public class SchemaGetFieldAPI {
-  private final SchemaHandler schemaHandler;
-
-  public SchemaGetFieldAPI(SchemaHandler schemaHandler) {
-    this.schemaHandler = schemaHandler;
-  }
-
-  @EndPoint(
-      path = {"/schema/fields/{field}"},
-      method = GET,
-      permission = PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public void retrieveFieldInfo(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    schemaHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetFieldTypeAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetFieldTypeAPI.java
deleted file mode 100644
index 1a4b182dae9..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaGetFieldTypeAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API for getting information about a single field-type definition from an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/fieldtypes/typeName) is analogous to the
- * v1 /solr/collectionName/schema/fieldtypes/typeName API.
- */
-public class SchemaGetFieldTypeAPI {
-  private final SchemaHandler schemaHandler;
-
-  public SchemaGetFieldTypeAPI(SchemaHandler schemaHandler) {
-    this.schemaHandler = schemaHandler;
-  }
-
-  @EndPoint(
-      path = {"/schema/fieldtypes/{name}"},
-      method = GET,
-      permission = PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public void getSingleFieldType(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    schemaHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllCopyFieldsAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllCopyFieldsAPI.java
deleted file mode 100644
index ef3b6b4bd7e..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllCopyFieldsAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API for listing all copyfield's in an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/copyfields) is analogous to the v1
- * /solr/collectionName/schema/copyfields API.
- */
-public class SchemaListAllCopyFieldsAPI {
-  private final SchemaHandler schemaHandler;
-
-  public SchemaListAllCopyFieldsAPI(SchemaHandler schemaHandler) {
-    this.schemaHandler = schemaHandler;
-  }
-
-  @EndPoint(
-      path = {"/schema/copyfields"},
-      method = GET,
-      permission = PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public void getCopyFields(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    schemaHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllDynamicFieldsAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllDynamicFieldsAPI.java
deleted file mode 100644
index bd0f4cbd238..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllDynamicFieldsAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API for listing all dynamic field definitions in an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/dynamicfields) is analogous to the v1
- * /solr/collectionName/schema/dynamicfields API.
- */
-public class SchemaListAllDynamicFieldsAPI {
-  private final SchemaHandler schemaHandler;
-
-  public SchemaListAllDynamicFieldsAPI(SchemaHandler schemaHandler) {
-    this.schemaHandler = schemaHandler;
-  }
-
-  @EndPoint(
-      path = {"/schema/dynamicfields"},
-      method = GET,
-      permission = PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public void listDynamicFields(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    schemaHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllFieldTypesAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllFieldTypesAPI.java
deleted file mode 100644
index 22b0e1c2900..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllFieldTypesAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API for listing all field-type definitions in an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/fieldtypes) is analogous to the v1
- * /solr/collectionName/schema/fieldtypes API.
- */
-public class SchemaListAllFieldTypesAPI {
-  private final SchemaHandler schemaHandler;
-
-  public SchemaListAllFieldTypesAPI(SchemaHandler schemaHandler) {
-    this.schemaHandler = schemaHandler;
-  }
-
-  @EndPoint(
-      path = {"/schema/fieldtypes"},
-      method = GET,
-      permission = PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public void listFieldTypes(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    schemaHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllFieldsAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllFieldsAPI.java
deleted file mode 100644
index 070c02cafe7..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaListAllFieldsAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API listing all fields defined in an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/fields) is analogous to the v1
- * /solr/collectionName/schema/fields API.
- */
-public class SchemaListAllFieldsAPI {
-  private final SchemaHandler schemaHandler;
-
-  public SchemaListAllFieldsAPI(SchemaHandler schemaHandler) {
-    this.schemaHandler = schemaHandler;
-  }
-
-  @EndPoint(
-      path = {"/schema/fields"},
-      method = GET,
-      permission = PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public void listSchemaFields(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    schemaHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java
deleted file mode 100644
index 021d362fa3f..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaNameAPI.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.impl.BinaryResponseParser.BINARY_CONTENT_TYPE_V2;
-
-import com.fasterxml.jackson.annotation.JsonProperty;
-import javax.inject.Inject;
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import org.apache.solr.api.JerseyResource;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.core.SolrCore;
-import org.apache.solr.jersey.PermissionName;
-import org.apache.solr.jersey.SolrJerseyResponse;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API for checking the name of an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/name) is analogous to the v1
- * /solr/collectionName/schema/name API.
- */
-@Path("/collections/{collectionName}/schema/name")
-public class SchemaNameAPI extends JerseyResource {
-
-  private SolrCore solrCore;
-
-  @Inject
-  public SchemaNameAPI(SolrCore solrCore) {
-    this.solrCore = solrCore;
-  }
-
-  @GET
-  @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
-  @PermissionName(PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public GetSchemaNameResponse getSchemaName() throws Exception {
-    final GetSchemaNameResponse response = instantiateJerseyResponse(GetSchemaNameResponse.class);
-    final IndexSchema schema = solrCore.getLatestSchema();
-    if (null == schema.getSchemaName()) {
-      throw new SolrException(SolrException.ErrorCode.NOT_FOUND, "Schema has no name");
-    }
-
-    response.name = schema.getSchemaName();
-    return response;
-  }
-
-  /** Response for {@link SchemaNameAPI}. */
-  public static class GetSchemaNameResponse extends SolrJerseyResponse {
-    @JsonProperty("name")
-    public String name;
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaZkVersionAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaZkVersionAPI.java
deleted file mode 100644
index 9928b9d8123..00000000000
--- a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaZkVersionAPI.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.apache.solr.client.solrj.SolrRequest.METHOD.GET;
-
-import org.apache.solr.api.EndPoint;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.request.SolrQueryRequest;
-import org.apache.solr.response.SolrQueryResponse;
-import org.apache.solr.security.PermissionNameProvider;
-
-/**
- * V2 API for checking the ZK version of an in-use schema.
- *
- * <p>This API (GET /v2/collections/collectionName/schema/zkversion) is analogous to the v1
- * /solr/collectionName/schema/zkversion API.
- */
-public class SchemaZkVersionAPI {
-  private final SchemaHandler schemaHandler;
-
-  public SchemaZkVersionAPI(SchemaHandler schemaHandler) {
-    this.schemaHandler = schemaHandler;
-  }
-
-  @EndPoint(
-      path = {"/schema/zkversion"},
-      method = GET,
-      permission = PermissionNameProvider.Name.SCHEMA_READ_PERM)
-  public void getSchemaZkVersion(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
-    schemaHandler.handleRequestBody(req, rsp);
-  }
-}
diff --git a/solr/core/src/java/org/apache/solr/jersey/InjectionFactories.java b/solr/core/src/java/org/apache/solr/jersey/InjectionFactories.java
index d6111b15d19..f84090d4250 100644
--- a/solr/core/src/java/org/apache/solr/jersey/InjectionFactories.java
+++ b/solr/core/src/java/org/apache/solr/jersey/InjectionFactories.java
@@ -18,9 +18,11 @@
 package org.apache.solr.jersey;
 
 import static org.apache.solr.jersey.RequestContextKeys.SOLR_CORE;
+import static org.apache.solr.jersey.RequestContextKeys.SOLR_PARAMS;
 
 import javax.inject.Inject;
 import javax.ws.rs.container.ContainerRequestContext;
+import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
@@ -104,6 +106,24 @@ public class InjectionFactories {
     public void dispose(IndexSchema instance) {}
   }
 
+  public static class ReuseFromContextSolrParamsFactory implements Factory<SolrParams> {
+
+    private final ContainerRequestContext containerRequestContext;
+
+    @Inject
+    public ReuseFromContextSolrParamsFactory(ContainerRequestContext containerRequestContext) {
+      this.containerRequestContext = containerRequestContext;
+    }
+
+    @Override
+    public SolrParams provide() {
+      return (SolrParams) containerRequestContext.getProperty(SOLR_PARAMS);
+    }
+
+    @Override
+    public void dispose(SolrParams instance) {}
+  }
+
   public static class SingletonFactory<T> implements Factory<T> {
 
     private final T singletonVal;
diff --git a/solr/core/src/java/org/apache/solr/jersey/JerseyApplications.java b/solr/core/src/java/org/apache/solr/jersey/JerseyApplications.java
index d8e3568e540..0bed6862b49 100644
--- a/solr/core/src/java/org/apache/solr/jersey/JerseyApplications.java
+++ b/solr/core/src/java/org/apache/solr/jersey/JerseyApplications.java
@@ -21,6 +21,7 @@ import io.swagger.v3.oas.annotations.OpenAPIDefinition;
 import io.swagger.v3.oas.annotations.info.Info;
 import io.swagger.v3.oas.annotations.info.License;
 import java.util.Map;
+import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.response.SolrQueryResponse;
@@ -120,6 +121,9 @@ public class JerseyApplications {
               bindFactory(InjectionFactories.ReuseFromContextIndexSchemaFactory.class)
                   .to(IndexSchema.class)
                   .in(RequestScoped.class);
+              bindFactory(InjectionFactories.ReuseFromContextSolrParamsFactory.class)
+                  .to(SolrParams.class)
+                  .in(RequestScoped.class);
             }
           });
     }
diff --git a/solr/core/src/test/org/apache/solr/api/JerseyResourceTest.java b/solr/core/src/test/org/apache/solr/api/JerseyResourceTest.java
index f96e1cb94a2..5e6f193c4e6 100644
--- a/solr/core/src/test/org/apache/solr/api/JerseyResourceTest.java
+++ b/solr/core/src/test/org/apache/solr/api/JerseyResourceTest.java
@@ -23,7 +23,7 @@ import static org.apache.solr.jersey.container.ContainerRequestUtils.DEFAULT_SEC
 import java.net.URI;
 import javax.ws.rs.container.ContainerRequestContext;
 import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.handler.admin.api.SchemaNameAPI;
+import org.apache.solr.handler.admin.api.GetSchemaAPI;
 import org.glassfish.jersey.internal.MapPropertiesDelegate;
 import org.glassfish.jersey.server.ContainerRequest;
 import org.junit.Test;
@@ -38,12 +38,12 @@ public class JerseyResourceTest extends SolrTestCaseJ4 {
     resource.containerRequestContext = requestContext;
     assertTrue(requestContext.getPropertyNames().isEmpty());
 
-    final SchemaNameAPI.GetSchemaNameResponse returned =
-        resource.instantiateJerseyResponse(SchemaNameAPI.GetSchemaNameResponse.class);
+    final GetSchemaAPI.SchemaNameResponse returned =
+        resource.instantiateJerseyResponse(GetSchemaAPI.SchemaNameResponse.class);
 
     assertTrue(requestContext.getPropertyNames().contains(SOLR_JERSEY_RESPONSE));
-    final SchemaNameAPI.GetSchemaNameResponse stashed =
-        (SchemaNameAPI.GetSchemaNameResponse) requestContext.getProperty(SOLR_JERSEY_RESPONSE);
+    final GetSchemaAPI.SchemaNameResponse stashed =
+        (GetSchemaAPI.SchemaNameResponse) requestContext.getProperty(SOLR_JERSEY_RESPONSE);
     assertEquals(stashed, returned);
   }
 
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaAPITest.java
index 5aa3e3b8890..69e8a9ba686 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaAPITest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaAPITest.java
@@ -21,7 +21,11 @@ import static org.mockito.Mockito.when;
 
 import java.util.Map;
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.client.solrj.response.schema.SchemaResponse;
+import org.apache.solr.common.util.NamedList;
 import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.handler.SchemaHandler;
+import org.apache.solr.handler.api.V2ApiUtils;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
 import org.apache.solr.schema.SimilarityFactory;
@@ -55,6 +59,38 @@ public class GetSchemaAPITest extends SolrTestCaseJ4 {
     assertEquals("flagValue", response.schema.get("flagKey"));
   }
 
+  @Test
+  public void testLooksUpNameFromLatestCoreSchema() throws Exception {
+    when(mockSchema.getSchemaName()).thenReturn("expectedSchemaName");
+
+    final GetSchemaAPI.SchemaNameResponse response = api.getSchemaName();
+
+    assertEquals("expectedSchemaName", response.name);
+    assertNull(response.error);
+  }
+
+  /**
+   * Test the v2 to v1 response mapping for /schema/name
+   *
+   * <p>{@link SchemaHandler} uses the v2 {@link GetSchemaAPI} (and its response class {@link
+   * GetSchemaAPI.SchemaNameResponse}) internally to serve the v1 version of this functionality. So
+   * it's important to make sure that our response stays compatible with SolrJ - both because that's
+   * important in its own right and because that ensures we haven't accidentally changed the v1
+   * response format.
+   */
+  @Test
+  public void testResponseCanBeParsedBySolrJ() {
+    final NamedList<Object> squashedResponse = new NamedList<>();
+    final GetSchemaAPI.SchemaNameResponse typedResponse = new GetSchemaAPI.SchemaNameResponse();
+    typedResponse.name = "someName";
+
+    V2ApiUtils.squashIntoNamedList(squashedResponse, typedResponse);
+    final SchemaResponse.SchemaNameResponse solrjResponse = new SchemaResponse.SchemaNameResponse();
+    solrjResponse.setResponse(squashedResponse);
+
+    assertEquals("someName", solrjResponse.getSchemaName());
+  }
+
   @Test
   public void testReliesOnIndexSchemaWhenFetchingSimilarity() {
     final var map = new SimpleOrderedMap<Object>();
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaFieldsAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaFieldsAPITest.java
new file mode 100644
index 00000000000..03e134602a0
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaFieldsAPITest.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.util.SimpleOrderedMap;
+import org.apache.solr.schema.IndexSchema;
+import org.junit.Before;
+import org.junit.Test;
+
+/** Unit tests for {@link GetSchemaFieldAPI} */
+@SuppressWarnings("unchecked")
+public class GetSchemaFieldsAPITest extends SolrTestCaseJ4 {
+
+  private IndexSchema mockSchema;
+  private SolrParams mockParams;
+  private GetSchemaFieldAPI api;
+
+  private SimpleOrderedMap<Object> mockField;
+  private ArrayList<SimpleOrderedMap<Object>> mockFieldList;
+
+  @Before
+  public void setUpMocks() {
+    assumeWorkingMockito();
+
+    mockSchema = mock(IndexSchema.class);
+    mockParams = mock(SolrParams.class);
+    api = new GetSchemaFieldAPI(mockSchema, mockParams);
+
+    mockField = new SimpleOrderedMap<>();
+    mockField.add("name", "id");
+    mockField.add("type", "string");
+
+    mockFieldList = new ArrayList<>();
+    mockFieldList.add(mockField);
+  }
+
+  @Test
+  public void testReliesOnIndexSchemaWhenFetchingAllFields() {
+    when(mockSchema.getNamedPropertyValues("fields", mockParams))
+        .thenReturn(Map.of("fields", mockFieldList));
+
+    final var response = api.listSchemaFields();
+
+    assertNotNull(response);
+    assertCorrectListFields(response.fields);
+  }
+
+  @Test
+  public void testReliesOnIndexSchemaWhenFetchingSpecificField() {
+    when(mockSchema.getNamedPropertyValues("fields", mockParams))
+        .thenReturn(Map.of("fields", mockFieldList));
+
+    final var response = api.getFieldInfo("id");
+
+    assertNotNull(response);
+    assertCorrectField(response.fieldInfo);
+  }
+
+  @Test
+  public void testReliesOnIndexSchemaWhenFetchingCopyFields() {
+    when(mockSchema.getNamedPropertyValues("copyfields", mockParams))
+        .thenReturn(Map.of("copyFields", mockFieldList));
+
+    final var response = api.listCopyFields();
+
+    assertNotNull(response);
+    assertCorrectListFields(response.copyFields);
+  }
+
+  @Test
+  public void testReliesOnIndexSchemaWhenFetchingDynamicFields() {
+    when(mockSchema.getNamedPropertyValues("dynamicfields", mockParams))
+        .thenReturn(Map.of("dynamicFields", mockFieldList));
+
+    final var response = api.listDynamicFields();
+
+    assertNotNull(response);
+    assertCorrectListFields(response.dynamicFields);
+  }
+
+  @Test
+  public void testReliesOnIndexSchemaWhenFetchingSpecificDynamicField() {
+    when(mockSchema.getNamedPropertyValues("dynamicfields", mockParams))
+        .thenReturn(Map.of("dynamicFields", mockFieldList));
+
+    final var response = api.getDynamicFieldInfo("id");
+
+    assertNotNull(response);
+    assertCorrectField(response.dynamicFieldInfo);
+  }
+
+  @Test
+  public void testReliesOnIndexSchemaWhenFetchingFieldTypes() {
+    when(mockSchema.getNamedPropertyValues("fieldtypes", mockParams))
+        .thenReturn(Map.of("fieldTypes", mockFieldList));
+
+    final var response = api.listSchemaFieldTypes();
+
+    assertNotNull(response);
+    assertCorrectListFields(response.fieldTypes);
+  }
+
+  @Test
+  public void testReliesOnIndexSchemaWhenFetchingSpecificFieldType() {
+    when(mockSchema.getNamedPropertyValues("fieldtypes", mockParams))
+        .thenReturn(Map.of("fieldTypes", mockFieldList));
+
+    final var response = api.getFieldTypeInfo("id");
+
+    assertNotNull(response);
+    assertCorrectField(response.fieldTypeInfo);
+  }
+
+  private void assertCorrectListFields(List<Object> responseFields) {
+    assertNotNull(responseFields);
+
+    assertEquals(1, responseFields.size());
+    assertCorrectField((SimpleOrderedMap<?>) responseFields.get(0));
+  }
+
+  private void assertCorrectField(SimpleOrderedMap<?> responseField) {
+    assertEquals("id", responseField.get("name"));
+    assertEquals("string", responseField.get("type"));
+  }
+}
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaZkVersionAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaZkVersionAPITest.java
new file mode 100644
index 00000000000..b6476613fd2
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/GetSchemaZkVersionAPITest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.handler.admin.api;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.core.SolrCore;
+import org.apache.solr.schema.IndexSchema;
+import org.junit.Before;
+import org.junit.Test;
+
+/** Unit tests for {@link GetSchemaZkVersionAPI} */
+public class GetSchemaZkVersionAPITest extends SolrTestCaseJ4 {
+
+  private SolrCore mockCore;
+  private IndexSchema mockSchema;
+  private GetSchemaZkVersionAPI api;
+
+  @Before
+  public void setUpMocks() {
+    assumeWorkingMockito();
+
+    mockCore = mock(SolrCore.class);
+    mockSchema = mock(IndexSchema.class);
+    when(mockCore.getLatestSchema()).thenReturn(mockSchema);
+    api = new GetSchemaZkVersionAPI(mockCore);
+  }
+
+  @Test
+  public void testReturnsInvalidZkVersionWhenNotManagedIndexSchema() throws Exception {
+
+    final var response = api.getSchemaZkVersion(-1);
+
+    assertNotNull(response);
+    assertEquals(-1, response.zkversion);
+  }
+}
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/SchemaNameAPITest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/SchemaNameAPITest.java
deleted file mode 100644
index 003e626ad1a..00000000000
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/SchemaNameAPITest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.solr.handler.admin.api;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import org.apache.solr.SolrTestCaseJ4;
-import org.apache.solr.client.solrj.response.schema.SchemaResponse;
-import org.apache.solr.common.util.NamedList;
-import org.apache.solr.core.SolrCore;
-import org.apache.solr.handler.SchemaHandler;
-import org.apache.solr.handler.api.V2ApiUtils;
-import org.apache.solr.schema.IndexSchema;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-/** Unit tests for {@link SchemaNameAPI} */
-public class SchemaNameAPITest extends SolrTestCaseJ4 {
-
-  private SolrCore solrCore;
-  private IndexSchema schema;
-
-  @BeforeClass
-  public static void ensureWorkingMockito() {
-    assumeWorkingMockito();
-  }
-
-  @Before
-  public void initMocks() {
-    solrCore = mock(SolrCore.class);
-    schema = mock(IndexSchema.class);
-    when(solrCore.getLatestSchema()).thenReturn(schema);
-  }
-
-  @Test
-  public void testLooksUpNameFromLatestCoreSchema() throws Exception {
-    when(schema.getSchemaName()).thenReturn("expectedSchemaName");
-    final SchemaNameAPI nameApi = new SchemaNameAPI(solrCore);
-
-    final SchemaNameAPI.GetSchemaNameResponse response = nameApi.getSchemaName();
-
-    assertEquals("expectedSchemaName", response.name);
-    assertNull(response.error);
-  }
-
-  /**
-   * Test the v2 to v1 response mapping for /schema/name
-   *
-   * <p>{@link SchemaHandler} uses the v2 {@link SchemaNameAPI} (and its response class {@link
-   * SchemaNameAPI.GetSchemaNameResponse}) internally to serve the v1 version of this functionality.
-   * So it's important to make sure that our response stays compatible with SolrJ - both because
-   * that's important in its own right and because that ensures we haven't accidentally changed the
-   * v1 response format.
-   */
-  @Test
-  public void testResponseCanBeParsedBySolrJ() {
-    final NamedList<Object> squashedResponse = new NamedList<>();
-    final SchemaNameAPI.GetSchemaNameResponse typedResponse =
-        new SchemaNameAPI.GetSchemaNameResponse();
-    typedResponse.name = "someName";
-
-    V2ApiUtils.squashIntoNamedList(squashedResponse, typedResponse);
-    final SchemaResponse.SchemaNameResponse solrjResponse = new SchemaResponse.SchemaNameResponse();
-    solrjResponse.setResponse(squashedResponse);
-
-    assertEquals("someName", solrjResponse.getSchemaName());
-  }
-}
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/api/V2SchemaAPIMappingTest.java b/solr/core/src/test/org/apache/solr/handler/admin/api/V2SchemaAPIMappingTest.java
index cb34f8a482e..3b1cab9b049 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/api/V2SchemaAPIMappingTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/V2SchemaAPIMappingTest.java
@@ -26,14 +26,6 @@ public class V2SchemaAPIMappingTest extends V2ApiMappingTest<SchemaHandler> {
 
   @Override
   public void populateApiBag() {
-    apiBag.registerObject(new SchemaZkVersionAPI(getRequestHandler()));
-    apiBag.registerObject(new SchemaListAllFieldsAPI(getRequestHandler()));
-    apiBag.registerObject(new SchemaGetFieldAPI(getRequestHandler()));
-    apiBag.registerObject(new SchemaListAllCopyFieldsAPI(getRequestHandler()));
-    apiBag.registerObject(new SchemaListAllDynamicFieldsAPI(getRequestHandler()));
-    apiBag.registerObject(new SchemaGetDynamicFieldAPI(getRequestHandler()));
-    apiBag.registerObject(new SchemaListAllFieldTypesAPI(getRequestHandler()));
-    apiBag.registerObject(new SchemaGetFieldTypeAPI(getRequestHandler()));
     apiBag.registerObject(new SchemaBulkModifyAPI(getRequestHandler()));
   }
 
@@ -47,18 +39,6 @@ public class V2SchemaAPIMappingTest extends V2ApiMappingTest<SchemaHandler> {
     return true;
   }
 
-  @Test
-  public void testGetSchemaInfoApis() {
-    assertAnnotatedApiExistsFor("GET", "/schema/dynamicfields");
-    assertAnnotatedApiExistsFor("GET", "/schema/dynamicfields/someDynamicField");
-    assertAnnotatedApiExistsFor("GET", "/schema/fieldtypes");
-    assertAnnotatedApiExistsFor("GET", "/schema/fieldtypes/someFieldType");
-    assertAnnotatedApiExistsFor("GET", "/schema/fields");
-    assertAnnotatedApiExistsFor("GET", "/schema/fields/someField");
-    assertAnnotatedApiExistsFor("GET", "/schema/copyfields");
-    assertAnnotatedApiExistsFor("GET", "/schema/zkversion");
-  }
-
   @Test
   public void testSchemaBulkModificationApiMapping() {
     assertAnnotatedApiExistsFor("POST", "/schema");