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 2022/06/08 10:32:43 UTC

[solr] branch main updated: SOLR-15740: Convert v2 schema-edit APIs to annotations (#896)

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

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


The following commit(s) were added to refs/heads/main by this push:
     new ab6d77a13d9 SOLR-15740: Convert v2 schema-edit APIs to annotations (#896)
ab6d77a13d9 is described below

commit ab6d77a13d9e5ce6c699f26e9d9e9d8d6b81c17e
Author: Jason Gerlowski <ge...@apache.org>
AuthorDate: Wed Jun 8 06:32:38 2022 -0400

    SOLR-15740: Convert v2 schema-edit APIs to annotations (#896)
    
    Solr's been in the slow process of moving its v2 APIs away from the
    existing apispec/mapping framework towards one that relies on more
    explicit annotations to specify API properties.
    
    This commit converts all of Solr's schema-edit APIs to a single
    annotation-based endpoint.
    
    Note that the details of this conversion cause the introspect output of
    this API to be lost.
---
 .../org/apache/solr/handler/SchemaHandler.java     | 37 ++++----
 .../handler/admin/api/SchemaBulkModifyAPI.java     | 57 +++++++++++++
 .../solr/handler/admin/V2ApiMappingTest.java       |  6 +-
 .../handler/admin/api/V2SchemaAPIMappingTest.java  | 76 +++++++++++++++++
 .../apispec/core.SchemaEdit.addCopyField.json      | 27 ------
 .../apispec/core.SchemaEdit.addField.json          | 98 ----------------------
 .../core.SchemaEdit.addFieldType.analyzers.json    | 51 -----------
 .../apispec/core.SchemaEdit.addFieldType.json      | 53 ------------
 .../apispec/core.SchemaEdit.deleteCopyField.json   | 19 -----
 .../core.SchemaEdit.deleteDynamicField.json        | 12 ---
 .../apispec/core.SchemaEdit.deleteField.json       | 12 ---
 .../apispec/core.SchemaEdit.deleteFieldType.json   | 14 ----
 .../src/resources/apispec/core.SchemaEdit.json     | 47 -----------
 .../apache/solr/common/util/JsonValidatorTest.java |  1 -
 14 files changed, 153 insertions(+), 357 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 1a6a09bbd16..13f779fe1fa 100644
--- a/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/SchemaHandler.java
@@ -46,6 +46,7 @@ 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.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;
@@ -312,24 +313,24 @@ public class SchemaHandler extends RequestHandlerBase
 
   @Override
   public Collection<Api> getApis() {
-    final List<Api> immList = ApiBag.wrapRequestHandlers(this, "core.SchemaEdit");
-    final List<Api> mutList = new ArrayList<>();
-    mutList.addAll(immList);
-    mutList.addAll(AnnotatedApi.getApis(new SchemaNameAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaInfoAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaUniqueKeyAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaVersionAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaSimilarityAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaZkVersionAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaListAllFieldsAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaGetFieldAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaListAllCopyFieldsAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaListAllDynamicFieldsAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaGetDynamicFieldAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaListAllFieldTypesAPI(this)));
-    mutList.addAll(AnnotatedApi.getApis(new SchemaGetFieldTypeAPI(this)));
-
-    return mutList;
+
+    final List<Api> apis = new ArrayList<>();
+    apis.addAll(AnnotatedApi.getApis(new SchemaNameAPI(this)));
+    apis.addAll(AnnotatedApi.getApis(new SchemaInfoAPI(this)));
+    apis.addAll(AnnotatedApi.getApis(new SchemaUniqueKeyAPI(this)));
+    apis.addAll(AnnotatedApi.getApis(new SchemaVersionAPI(this)));
+    apis.addAll(AnnotatedApi.getApis(new SchemaSimilarityAPI(this)));
+    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;
   }
 
   @Override
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaBulkModifyAPI.java b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaBulkModifyAPI.java
new file mode 100644
index 00000000000..22b82bf3960
--- /dev/null
+++ b/solr/core/src/java/org/apache/solr/handler/admin/api/SchemaBulkModifyAPI.java
@@ -0,0 +1,57 @@
+/*
+ * 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.POST;
+
+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 APIs for creating, updating, or deleting individual components in a collection's schema.
+ *
+ * <p>This API (POST /v2/collections/collectionName/schema {...}) is analogous to the commands
+ * supported by the v1 POST /collectionName/schema API.
+ *
+ * <p>Typically v2 "POST" API implementations separate each "command" into a different method. This
+ * is not done here because the v1 API code in SchemaHandler expects to consume the request body
+ * itself (meaning that nothing _before_ SchemaHandler can consume the request body).
+ *
+ * <p>As a result the single method below handles all "commands" supported by the POST /schema API:
+ * 'add-field', 'delete-field', 'replace-field', 'add-dynamic-field', 'delete-dynamic-field',
+ * 'replace-dynamic-field', 'add-field-type', 'delete-field-type', 'replace-field-type',
+ * 'add-copy-field', and 'delete-copy-field'.
+ */
+public class SchemaBulkModifyAPI {
+  private final SchemaHandler schemaHandler;
+
+  public SchemaBulkModifyAPI(SchemaHandler schemaHandler) {
+    this.schemaHandler = schemaHandler;
+  }
+
+  @EndPoint(
+      path = {"/schema"},
+      method = POST,
+      permission = PermissionNameProvider.Name.SCHEMA_EDIT_PERM)
+  public void bulkModifySchema(SolrQueryRequest req, SolrQueryResponse rsp) throws Exception {
+    schemaHandler.handleRequestBody(req, rsp);
+  }
+}
diff --git a/solr/core/src/test/org/apache/solr/handler/admin/V2ApiMappingTest.java b/solr/core/src/test/org/apache/solr/handler/admin/V2ApiMappingTest.java
index 0fb21697d8a..c52e9626d68 100644
--- a/solr/core/src/test/org/apache/solr/handler/admin/V2ApiMappingTest.java
+++ b/solr/core/src/test/org/apache/solr/handler/admin/V2ApiMappingTest.java
@@ -207,11 +207,7 @@ public abstract class V2ApiMappingTest<T extends RequestHandlerBase> extends Sol
   protected void assertAnnotatedApiExistsFor(String method, String path) {
     final AnnotatedApi api = getAnnotatedApiFor(method, path);
     assertTrue(
-        "Expected to find API mapping for method ["
-            + method
-            + "] on path ["
-            + path
-            + "], but none found!",
+        "Expected to find API mapping for [" + method + " " + path + "] but none found!",
         api != null);
   }
 
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
new file mode 100644
index 00000000000..4ef6f71b319
--- /dev/null
+++ b/solr/core/src/test/org/apache/solr/handler/admin/api/V2SchemaAPIMappingTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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 org.apache.solr.handler.SchemaHandler;
+import org.apache.solr.handler.admin.V2ApiMappingTest;
+import org.junit.Test;
+
+/** Unit tests for the GET and POST /v2/c/collectionName/schema APIs. */
+public class V2SchemaAPIMappingTest extends V2ApiMappingTest<SchemaHandler> {
+
+  @Override
+  public void populateApiBag() {
+    apiBag.registerObject(new SchemaNameAPI(getRequestHandler()));
+    apiBag.registerObject(new SchemaInfoAPI(getRequestHandler()));
+    apiBag.registerObject(new SchemaUniqueKeyAPI(getRequestHandler()));
+    apiBag.registerObject(new SchemaVersionAPI(getRequestHandler()));
+    apiBag.registerObject(new SchemaSimilarityAPI(getRequestHandler()));
+    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()));
+  }
+
+  @Override
+  public SchemaHandler createUnderlyingRequestHandler() {
+    return createMock(SchemaHandler.class);
+  }
+
+  @Override
+  public boolean isCoreSpecific() {
+    return true;
+  }
+
+  @Test
+  public void testGetSchemaInfoApis() {
+    assertAnnotatedApiExistsFor("GET", "/schema");
+    assertAnnotatedApiExistsFor("GET", "/schema/name");
+    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/similarity");
+    assertAnnotatedApiExistsFor("GET", "/schema/uniquekey");
+    assertAnnotatedApiExistsFor("GET", "/schema/version");
+    assertAnnotatedApiExistsFor("GET", "/schema/zkversion");
+  }
+
+  @Test
+  public void testSchemaBulkModificationApiMapping() throws Exception {
+    assertAnnotatedApiExistsFor("POST", "/schema");
+  }
+}
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.addCopyField.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.addCopyField.json
deleted file mode 100644
index d3dc92d82ac..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.addCopyField.json
+++ /dev/null
@@ -1,27 +0,0 @@
-{
-  "documentation" : "https://solr.apache.org/guide/schema-api.html#add-a-new-copy-field-rule",
-  "description": "Adds a new copy field rule, to allow one field to be populated with the contents of one or more other fields.",
-  "type": "object",
-  "properties": {
-    "source": {
-      "type": "string",
-      "description": "The field to copy from."
-    },
-    "dest": {
-      "type":"array",
-      "items": {
-        "type": "string"
-      },
-      "description": "A field or an array of fields to which the source field will be copied. A wildcard for a dynamic field can be used, but only if the source field also contains a dynamic field."
-    },
-    "maxChars": {
-      "type": "integer",
-      "description": "An upper limit for the number of characters to be copied. This would be useful if index size is a concern. If a limit is not specified, the entire field will be copied."
-    }
-  },
-  "required": [
-    "source",
-    "dest"
-  ]
-
-}
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.addField.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.addField.json
deleted file mode 100644
index 8ee1583a48c..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.addField.json
+++ /dev/null
@@ -1,98 +0,0 @@
-{
-  "documentation" :"https://solr.apache.org/guide/schema-api.html",
-  "type":"object",
-  "properties":{
-    "name": {
-      "type": "string",
-      "description": "The name of the field. Names should be alphanumeric or underscore characters only, and not start with a digit. Names also cannot begin and end with an underscore, as such field names are reserved by the system."
-    },
-    "type": {
-      "type": "string",
-      "description":"The name of the fieldType for this field."
-    },
-    "defaultValue": {
-      "type": "string",
-      "description": "An optional default value that should be added automatically to any document that does not have a value for this field."
-    },
-    "indexed": {
-      "type": "boolean",
-      "description": "If true, the field will be indexed and will be available for use in queries to retrieve matching documents. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to true.",
-      "default": "true"
-    },
-    "stored": {
-      "type": "boolean",
-      "description": "If true, the actual value of the field can be retrieved by queries and be displayed in results. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to true.",
-      "default":"true"
-    },
-    "omitNorms": {
-      "type": "boolean",
-      "description": "If true, length normalization and index-time boosting for a field are omitted from the index. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to true for all primitive field types (such as dates, strings, boolean, and numeric fields), but will default to false for non-primitive field types."
-    },
-    "omitTermFreqAndPositions": {
-      "type": "boolean",
-      "description": "If true, all term frequency, positions, and payloads will not be indexed. This means that phrase queries, proximity queries and similar queries that rely on analysis of the frequency of a query term or the position of a term to other terms will not be supported. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to true for all field types that are not text fields."
-    },
-    "termVectors": {
-      "type": "boolean",
-      "description": "If true, term vectors will be stored which can be used to optimize More Like This and optimizing highlighting wildcard queries. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false.",
-      "default": "false"
-    },
-    "termPositions": {
-      "type": "boolean",
-      "description": "If true, term vectors will include positions. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false.",
-      "default": "false"
-    },
-    "termOffsets": {
-      "type": "boolean",
-      "description": "If true, term vectors will include offsets. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false.",
-      "default": "false"
-    },
-    "multiValued": {
-      "type": "boolean",
-      "description": "If true, a single document can have multiple values in a single field, and these values will be indexed. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false.",
-      "default": "false"
-    },
-    "sortMissingFirst": {
-      "type": "boolean",
-      "description": "If true, when sorting by the field, any documents missing a value for the field will be placed at the top of the list. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false. If sortMissingFirst and sortMissingLast are both false, documents missing this field will be placed at the top when sorting in ascending order (asc) or at the bottom when sorting in descending order (desc).",
-      "default": "false"
-    },
-    "sortMissingLast": {
-      "type": "boolean",
-      "description": "If true, when sorting by the field, any documents missing a value for the field will be placed at the bottom of the list. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false. If sortMissingFirst and sortMissingLast are both false, documents missing this field will be placed at the top when sorting in ascending order (asc) or at the bottom when sorting in descending order (desc).",
-      "default": "false"
-    },
-    "required": {
-      "type": "boolean",
-      "description": "If true, any document that does not have a value for the field will be rejected. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false.",
-      "default": "false"
-    },
-    "omitPositions": {
-      "type": "boolean",
-      "description": "If true, information about the position of terms in a document will not be stored in the index, which means phrase queries, proximity queries, and similar will not be supported for this field. It is similar to 'omitTermFreqAndPositions', but 'omitPositions' will allow term frequency information to be stored. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to true for all field types that [...]
-    },
-    "storeOffsetsWithPositions": {
-      "type": "boolean",
-      "description": "If true, term offsets will be stored with positions in the postings list in the index. This optimizes highlighting with the UnifiedHighlighter. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false.",
-      "default": "false"
-    },
-    "docValues": {
-      "type": "boolean",
-      "description": "If true, field values will be stored in a column-oriented docValues structure. This can be more efficient for some fields, particularly those used for faceting. More information is available from https://solr.apache.org/guide/docvalues.html. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to true for all non-text fields (such as dates, integers, longs, etc.)."
-    },
-    "termPayloads": {
-      "type": "boolean",
-      "description": "If true, term vectors will include payloads. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to false.",
-      "default": "false"
-    },
-    "useDocValuesAsStored": {
-      "type": "boolean",
-      "description": "If true and docValues are enabled for the field, the field will be returned when all fields are requested (using '*' with the fl parameter), even if it is not stored. If this is not defined, it will inherit the value from the fieldType. If the fieldType does not define a value, it will default to true.",
-      "default": "true"
-    }
-  },
-  "required": [
-    "name",
-    "type"
-  ]
-}
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.addFieldType.analyzers.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.addFieldType.analyzers.json
deleted file mode 100644
index 2974a60554e..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.addFieldType.analyzers.json
+++ /dev/null
@@ -1,51 +0,0 @@
-{
-  "type": "object",
-  "properties": {
-    "class": {
-      "type": "string"
-    },
-    "charFilters": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "class": {
-            "type": "string"
-          }
-        },
-        "required": [
-          "class"
-        ],
-        "additionalProperties": true
-      }
-    },
-    "tokenizer": {
-      "type": "object",
-      "properties": {
-        "class": {
-          "type": "string"
-        }
-      },
-      "required": [
-        "class"
-      ],
-      "additionalProperties": true
-    },
-    "filters": {
-      "type": "array",
-      "items": {
-        "type": "object",
-        "properties": {
-          "class": {
-            "type": "string"
-          }
-        },
-        "required": [
-          "class"
-        ],
-        "additionalProperties": true
-      }
-    }
-  },
-  "additionalProperties": true
-}
\ No newline at end of file
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.addFieldType.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.addFieldType.json
deleted file mode 100644
index 99bca980620..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.addFieldType.json
+++ /dev/null
@@ -1,53 +0,0 @@
-{
-  "type":"object",
-  "properties": {
-    "name": {
-      "type": "string",
-      "description": "The name of the field type. This name is used when defining a field. It is strongly recommended that field type names consist only of alphanumeric or underscore characters and not start with a digit."
-    },
-    "class": {
-      "type": "string",
-      "description": "The class name to use for the field type. Class names do not need to be fully qualified if they are included with Solr, so instead of 'org.apache.solr.schema.TextField', you can abbreviate the name as 'solr.TextField'. Custom or third-party class names may need to be fully qualified, however."
-    },
-    "positionIncrementGap": {
-      "type": "integer",
-      "description": "The distance between the values of a multivalued field. This is used to prevent inaccurate phrase matches across two separate values of the same field.",
-      "default": "0"
-    },
-    "autoGeneratePhraseQueries": {
-      "type": "boolean",
-      "description": "If true, phrase queries will automatically be generated for adjacent terms. If false, terms must also be enclosed in double-quotes to be treated as phrases.",
-      "default": "false"
-    },
-    "docValuesFormat": {
-      "type": "string",
-      "description": "Defines a custom DocValuesFormat to use for fields of this type. A custom DocValuesFormat requires that a schema-aware codec has also been configured in solrconfig.xml."
-    },
-    "postingsFormat": {
-      "type": "string",
-      "description": "Defines a custom PostingsFormat to use for fields of this type. A custom PostingsFormat requires that a schema-aware codec has also been configured in solrconfig.xml."
-    },
-    "queryAnalyzer": {
-      "description": "A query analyzer section defines how incoming queries to Solr will be analyzed for a field of this type.",
-      "#include": "core.SchemaEdit.addFieldType.analyzers"
-    },
-    "indexAnalyzer": {
-      "description": "An index analyzer section defines how incoming text in documents will be analyzed for a field of this type.",
-      "#include": "core.SchemaEdit.addFieldType.analyzers"
-    },
-    "multiTermAnalyzer": {
-      "description": "A multiterm analyzer section defines how incoming queries that results in Multi-Term expansion will be analyzed for a field of this type.",
-      "documentation": "https://solr.apache.org/guide/analyzers.html#analysis-for-multi-term-expansion",
-      "#include": "core.SchemaEdit.addFieldType.analyzers"
-    },
-    "analyzer": {
-      "description": "An analyzer defines how both incoming text in documents and queries are analyzed for a field of this type. If a query analyzer and an index analyzer have both been defined, a general analyzer does not need to be defined for this type.",
-      "#include": "core.SchemaEdit.addFieldType.analyzers"
-    }
-  },
-  "additionalProperties": true,
-  "required": [
-    "name",
-    "class"
-  ]
-}
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteCopyField.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteCopyField.json
deleted file mode 100644
index c0853ace529..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteCopyField.json
+++ /dev/null
@@ -1,19 +0,0 @@
-{
-  "type":"object",
-  "documentation": "https://solr.apache.org/guide/schema-api.html#delete-a-copy-field-rule",
-  "description": "Deletes a copy field rule. Both sides of the copy rule (source and destination) are required in order to delete the rule.",
-  "properties":{
-    "source": {
-      "type":"string",
-      "description": "The field the copy rule is defined to copy from."
-    },
-    "dest": {
-      "type": "string",
-      "description": "The field the copy rule is defined to copy to."
-    }
-  },
-  "required": [
-    "source",
-    "dest"
-  ]
-}
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteDynamicField.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteDynamicField.json
deleted file mode 100644
index a8fc8a49599..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteDynamicField.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "documentation": "https://solr.apache.org/guide/schema-api.html#delete-a-dynamic-field-rule",
-  "description": "Deletes a dynamic field.",
-  "type":"object",
-  "properties": {
-    "name": {
-      "type": "string",
-      "description": "The name of the dynamic field to delete."
-    }
-  },
-  "required":["name"]
-}
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteField.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteField.json
deleted file mode 100644
index eedf41a7e58..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteField.json
+++ /dev/null
@@ -1,12 +0,0 @@
-{
-  "documentation" : "https://solr.apache.org/guide/schema-api.html#delete-a-field",
-  "description": "Deletes a field from the schema.",
-  "type":"object",
-  "properties":{
-    "name":{
-     "description" :"The name of the field to delete.",
-      "type" : "string"
-    }
-  },
-  "required" : ["name"]
-}
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteFieldType.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteFieldType.json
deleted file mode 100644
index 920260d40be..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.deleteFieldType.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "documentation":"https://solr.apache.org/guide/schema-api.html#delete-a-field-type",
-  "description": "Deletes a field type from the schema.",
-  "type":"object",
-  "properties": {
-    "name": {
-      "type": "string",
-      "description": "The name of the field type to delete."
-    }
-  },
-  "required": [
-    "name"
-  ]
-}
diff --git a/solr/solrj/src/resources/apispec/core.SchemaEdit.json b/solr/solrj/src/resources/apispec/core.SchemaEdit.json
deleted file mode 100644
index 05ca06ceb79..00000000000
--- a/solr/solrj/src/resources/apispec/core.SchemaEdit.json
+++ /dev/null
@@ -1,47 +0,0 @@
-{
-  "documentation": "https://solr.apache.org/guide/schema-api.html",
-  "description": "The Schema API provides viewing, editing, adding, and deleting elements of Solr's schema. This API can only be used if Managed Schema is enabled and the schema is defined as mutable. See https://solr.apache.org/guide/schema-factory-definition-in-solrconfig.html for more information about enabling Managed Schema.",
-  "methods": [
-    "POST"
-  ],
-  "url": {
-    "paths": [
-      "$handlerName"
-    ]
-  },
-  "commands": {
-    "add-field": {
-      "#include": "core.SchemaEdit.addField"
-    },
-    "delete-field": {
-      "#include": "core.SchemaEdit.deleteField"
-    },
-    "replace-field": {
-      "#include": "core.SchemaEdit.addField"
-    },
-    "add-dynamic-field": {
-      "#include": "core.SchemaEdit.addField"
-    },
-    "delete-dynamic-field": {
-      "#include": "core.SchemaEdit.deleteDynamicField"
-    },
-    "replace-dynamic-field": {
-      "#include": "core.SchemaEdit.addField"
-    },
-    "add-field-type": {
-      "#include": "core.SchemaEdit.addFieldType"
-    },
-    "delete-field-type": {
-      "#include": "core.SchemaEdit.deleteFieldType"
-    },
-    "replace-field-type": {
-      "#include": "core.SchemaEdit.addFieldType"
-    },
-    "add-copy-field": {
-      "#include": "core.SchemaEdit.addCopyField"
-    },
-    "delete-copy-field": {
-      "#include": "core.SchemaEdit.deleteCopyField"
-    }
-  }
-}
diff --git a/solr/solrj/src/test/org/apache/solr/common/util/JsonValidatorTest.java b/solr/solrj/src/test/org/apache/solr/common/util/JsonValidatorTest.java
index 4ff39cdcd52..d6e6361f3e9 100644
--- a/solr/solrj/src/test/org/apache/solr/common/util/JsonValidatorTest.java
+++ b/solr/solrj/src/test/org/apache/solr/common/util/JsonValidatorTest.java
@@ -25,7 +25,6 @@ public class JsonValidatorTest extends SolrTestCaseJ4 {
   public void testSchema() {
     checkSchema("cluster.security.BasicAuth.Commands");
     checkSchema("cluster.security.RuleBasedAuthorization");
-    checkSchema("core.SchemaEdit");
   }
 
   public void testSchemaValidation() {