diff --git a/dev-tools/scripts/smokeTestRelease.py b/dev-tools/scripts/smokeTestRelease.py
index 50b517aae59..554c664559d 100755
--- a/dev-tools/scripts/smokeTestRelease.py
+++ b/dev-tools/scripts/smokeTestRelease.py
@@ -606,7 +606,7 @@ def verifyUnpacked(java, artifact, unpackPath, gitRevision, version, testArgs):
expected_src_root_folders = ['buildSrc', 'dev-docs', 'dev-tools', 'gradle', 'help', 'solr']
expected_src_root_files = ['build.gradle', 'gradlew', 'gradlew.bat', 'settings.gradle', 'versions.lock', 'versions.props']
expected_src_solr_files = ['build.gradle']
- expected_src_solr_folders = ['benchmark', 'bin', 'modules', 'core', 'docker', 'documentation', 'example', 'licenses', 'packaging', 'distribution', 'prometheus-exporter', 'server', 'solr-ref-guide', 'solrj', 'solrj-streaming', 'solrj-zookeeper', 'test-framework', 'webapp', '.gitignore', '.gitattributes']
+ expected_src_solr_folders = ['benchmark', 'bin', 'modules', 'api', 'core', 'docker', 'documentation', 'example', 'licenses', 'packaging', 'distribution', 'prometheus-exporter', 'server', 'solr-ref-guide', 'solrj', 'solrj-streaming', 'solrj-zookeeper', 'test-framework', 'webapp', '.gitignore', '.gitattributes']
is_in_list(in_root_folder, expected_src_root_folders)
is_in_list(in_root_folder, expected_src_root_files)
is_in_list(in_solr_folder, expected_src_solr_folders)
diff --git a/gradle/maven/defaults-maven.gradle b/gradle/maven/defaults-maven.gradle
index 936de2c0988..8d0ef8f2a43 100644
--- a/gradle/maven/defaults-maven.gradle
+++ b/gradle/maven/defaults-maven.gradle
@@ -24,6 +24,7 @@
configure(rootProject) {
ext {
published = [
+ ":solr:api",
":solr:core",
":solr:solrj",
":solr:solrj-streaming",
diff --git a/gradle/solr/packaging.gradle b/gradle/solr/packaging.gradle
index b1993ab8194..bb3fd5703ab 100644
--- a/gradle/solr/packaging.gradle
+++ b/gradle/solr/packaging.gradle
@@ -58,6 +58,7 @@ configure(allprojects.findAll {project -> project.path.startsWith(":solr:modules
dependencies {
solrPlatformLibs project(":solr:core")
solrPlatformLibs project(":solr:solrj")
+ solrPlatformLibs project(":solr:api")
solrPlatformLibs project(":solr:solrj-zookeeper")
// libExt has logging libs, which we don't want. Lets users decide what they want.
solrPlatformLibs project(path: ":solr:server", configuration: 'libExt')
diff --git a/gradle/validation/spotless.gradle b/gradle/validation/spotless.gradle
index 3239ac4b1a3..a8cb41e0f39 100644
--- a/gradle/validation/spotless.gradle
+++ b/gradle/validation/spotless.gradle
@@ -26,18 +26,32 @@ configure(project(":solr").subprojects) { prj ->
plugins.withType(JavaPlugin) {
prj.apply plugin: 'com.diffplug.spotless'
- spotless {
- java {
- toggleOffOn() // obviously, only to be used sparingly.
+ ext {
+ spotlessJavaSetup = (Action){
+ it.toggleOffOn() // obviously, only to be used sparingly.
// TODO: Work out how to support multiple different header files (we have
// classes in the codebase that have original headers). We currently use
// Apache RAT to enforce headers so this is of lesser priority.
//
- // licenseHeaderFile file("${resources}/asl-header.txt"), '^(\\s*package)'
+ // it.licenseHeaderFile(file("${resources}/asl-header.txt"), '^(\\s*package)')
+ it.setLineEndings(Enum.valueOf(rootProject.buildscript.classLoader.loadClass("com.diffplug.spotless.LineEnding"), "UNIX"))
+ it.endWithNewline()
+ it.googleJavaFormat('1.15.0')
- lineEndings 'UNIX'
- endWithNewline()
- googleJavaFormat('1.15.0')
+ it.custom('Refuse wildcard imports', { line ->
+ // Wildcard imports can't be resolved by spotless itself.
+ // This will require the developer themselves to adhere to best practices.
+ if (line =~ /\nimport .*\*;/) {
+ throw new AssertionError("Do not use wildcard imports. 'spotlessApply' cannot resolve this issue.")
+ }
+ line
+ })
+ }
+ }
+
+ spotless {
+ java {
+ prj.ext.spotlessJavaSetup.execute(it)
// Apply to all Java sources
target "src/**/*.java"
@@ -62,14 +76,6 @@ configure(project(":solr").subprojects) { prj ->
target "modules/**/examples/*.java"
break
}
-
- custom 'Refuse wildcard imports', {
- // Wildcard imports can't be resolved by spotless itself.
- // This will require the developer themselves to adhere to best practices.
- if (it =~ /\nimport .*\*;/) {
- throw new AssertionError("Do not use wildcard imports. 'spotlessApply' cannot resolve this issue.")
- }
- }
}
}
diff --git a/settings.gradle b/settings.gradle
index 65235015950..f0a1ff11538 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -26,6 +26,7 @@ rootProject.name = "solr-root"
includeBuild("dev-tools/solr-missing-doclet")
+include "solr:api"
include "solr:solrj"
include "solr:solrj-zookeeper"
include "solr:solrj-streaming"
diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt
index b4c7f498832..bbc85e009f4 100644
--- a/solr/CHANGES.txt
+++ b/solr/CHANGES.txt
@@ -84,6 +84,11 @@ Improvements
a HTTP 503 status. Switched to 510 so that CloudSolrClient will auto-retry it and probably succeed.
(David Smiley, Alex Deparvu)
+* SOLR-16825: Solr now offers `SolrRequest` implementations for a subset of its v2 APIs. These implementations
+ are experimental and should be used with caution, but may be preferable to their v1 counterparts in some
+ circumstances as they are generated and more likely to remain up-to-date with future API changes.
+ (Jason Gerlowski, David Smiley, Houston Putman)
+
Optimizations
---------------------
diff --git a/solr/api/build.gradle b/solr/api/build.gradle
new file mode 100644
index 00000000000..f61977993af
--- /dev/null
+++ b/solr/api/build.gradle
@@ -0,0 +1,61 @@
+/*
+ * 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.
+ */
+
+plugins {
+ id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.2'
+}
+
+apply plugin: 'java-library'
+
+description = 'API - Interfaces and classes used to represent Solrs APIs'
+
+ext {
+ openApiSpecDir = "${buildDir}/generated/openapi"
+ openApiSpecFile = "${project.openApiSpecDir}/openapi.json"
+}
+
+configurations {
+ openapiSpec {
+ canBeConsumed = true
+ canBeResolved = false
+ }
+}
+
+resolve {
+ classpath = sourceSets.main.runtimeClasspath
+ outputDir = file(project.openApiSpecDir)
+ prettyPrint = true
+}
+
+dependencies {
+ runtimeOnly 'org.slf4j:slf4j-api'
+
+ implementation 'jakarta.ws.rs:jakarta.ws.rs-api'
+ implementation 'com.fasterxml.jackson.core:jackson-annotations'
+ api 'io.swagger.core.v3:swagger-annotations'
+ implementation 'org.semver4j:semver4j'
+
+ testImplementation project(':solr:test-framework')
+ testImplementation project(':solr:api')
+ testImplementation 'org.apache.lucene:lucene-test-framework'
+}
+
+artifacts {
+ openapiSpec resolve.outputDir, {
+ builtBy resolve
+ }
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/AddReplicaPropertyApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/AddReplicaPropertyApi.java
new file mode 100644
index 00000000000..d29ee057502
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/AddReplicaPropertyApi.java
@@ -0,0 +1,60 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.endpoint;
+
+import static org.apache.solr.client.api.util.Constants.BINARY_CONTENT_TYPE_V2;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.parameters.RequestBody;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import org.apache.solr.client.api.model.AddReplicaPropertyRequestBody;
+import org.apache.solr.client.api.model.SolrJerseyResponse;
+
+@Path("/collections/{collName}/shards/{shardName}/replicas/{replicaName}/properties/{propName}")
+public interface AddReplicaPropertyApi {
+
+ @PUT
+ @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
+ @Operation(
+ summary = "Adds a property to the specified replica",
+ tags = {"replicas"})
+ public SolrJerseyResponse addReplicaProperty(
+ @Parameter(
+ description = "The name of the collection the replica belongs to.",
+ required = true)
+ @PathParam("collName")
+ String collName,
+ @Parameter(description = "The name of the shard the replica belongs to.", required = true)
+ @PathParam("shardName")
+ String shardName,
+ @Parameter(description = "The replica, e.g., `core_node1`.", required = true)
+ @PathParam("replicaName")
+ String replicaName,
+ @Parameter(description = "The name of the property to add.", required = true)
+ @PathParam("propName")
+ String propertyName,
+ @RequestBody(
+ description = "The value of the replica property to create or update",
+ required = true)
+ AddReplicaPropertyRequestBody requestBody)
+ throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteAliasApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteAliasApi.java
new file mode 100644
index 00000000000..24759ead2ad
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteAliasApi.java
@@ -0,0 +1,45 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.endpoint;
+
+import static org.apache.solr.client.api.util.Constants.BINARY_CONTENT_TYPE_V2;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import org.apache.solr.client.api.model.SolrJerseyResponse;
+
+@Path("/aliases/{aliasName}")
+public interface DeleteAliasApi {
+
+ @DELETE
+ @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
+ @Operation(
+ summary = "Deletes an alias by its name",
+ tags = {"aliases"})
+ SolrJerseyResponse deleteAlias(
+ @Parameter(description = "The name of the alias to delete", required = true)
+ @PathParam("aliasName")
+ String aliasName,
+ @QueryParam("async") String asyncId)
+ throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteCollectionApi.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteCollectionApi.java
new file mode 100644
index 00000000000..9e28e7b1722
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/DeleteCollectionApi.java
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.endpoint;
+
+import static org.apache.solr.client.api.util.Constants.BINARY_CONTENT_TYPE_V2;
+
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import org.apache.solr.client.api.model.SubResponseAccumulatingJerseyResponse;
+
+@Path("/collections/{collectionName}")
+public interface DeleteCollectionApi {
+
+ @DELETE
+ @Produces({"application/json", "application/xml", BINARY_CONTENT_TYPE_V2})
+ @Operation(
+ summary = "Deletes a collection from SolrCloud",
+ tags = {"collections"})
+ SubResponseAccumulatingJerseyResponse deleteCollection(
+ @Parameter(description = "The name of the collection to be deleted.", required = true)
+ @PathParam("collectionName")
+ String collectionName,
+ @QueryParam("followAliases") Boolean followAliases,
+ @Parameter(description = "An ID to track the request asynchronously") @QueryParam("async")
+ String asyncId)
+ throws Exception;
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/endpoint/package-info.java b/solr/api/src/java/org/apache/solr/client/api/endpoint/package-info.java
new file mode 100644
index 00000000000..377e217fda9
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/endpoint/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** Interfaces representing individual Solr v2 APIs. */
+package org.apache.solr.client.api.endpoint;
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/AddReplicaPropertyRequestBody.java b/solr/api/src/java/org/apache/solr/client/api/model/AddReplicaPropertyRequestBody.java
new file mode 100644
index 00000000000..f78c7bebd9c
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/AddReplicaPropertyRequestBody.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import io.swagger.v3.oas.annotations.media.Schema;
+import org.apache.solr.client.api.util.ReflectWritable;
+
+public class AddReplicaPropertyRequestBody implements ReflectWritable {
+ public AddReplicaPropertyRequestBody() {}
+
+ public AddReplicaPropertyRequestBody(String value) {
+ this.value = value;
+ }
+
+ @Schema(description = "The value to assign to the property.", required = true)
+ @JsonProperty("value")
+ public String value;
+
+ @Schema(
+ description =
+ "If `true`, then setting this property in one replica will remove the property from all other replicas in that shard. The default is `false`.\\nThere is one pre-defined property `preferredLeader` for which `shardUnique` is forced to `true` and an error returned if `shardUnique` is explicitly set to `false`.",
+ defaultValue = "false")
+ @JsonProperty("shardUnique")
+ public Boolean shardUnique;
+}
diff --git a/solr/core/src/java/org/apache/solr/jersey/AsyncJerseyResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/AsyncJerseyResponse.java
similarity index 95%
rename from solr/core/src/java/org/apache/solr/jersey/AsyncJerseyResponse.java
rename to solr/api/src/java/org/apache/solr/client/api/model/AsyncJerseyResponse.java
index af08d227172..08651598d9d 100644
--- a/solr/core/src/java/org/apache/solr/jersey/AsyncJerseyResponse.java
+++ b/solr/api/src/java/org/apache/solr/client/api/model/AsyncJerseyResponse.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.solr.jersey;
+package org.apache.solr.client.api.model;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/solr/core/src/java/org/apache/solr/jersey/ErrorInfo.java b/solr/api/src/java/org/apache/solr/client/api/model/ErrorInfo.java
similarity index 74%
rename from solr/core/src/java/org/apache/solr/jersey/ErrorInfo.java
rename to solr/api/src/java/org/apache/solr/client/api/model/ErrorInfo.java
index 24ca06d64ff..1a6ca071642 100644
--- a/solr/core/src/java/org/apache/solr/jersey/ErrorInfo.java
+++ b/solr/api/src/java/org/apache/solr/client/api/model/ErrorInfo.java
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -15,19 +15,23 @@
* limitations under the License.
*/
-package org.apache.solr.jersey;
+package org.apache.solr.client.api.model;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;
import java.util.Map;
-import org.apache.solr.common.SolrException;
+import org.apache.solr.client.api.util.ReflectWritable;
/**
* A value type representing an error.
*
*
Based on the fields exposed in responses from Solr's v1/requestHandler API.
*/
-public class ErrorInfo implements JacksonReflectMapWriter {
+public class ErrorInfo implements ReflectWritable {
+
+ public static final String ROOT_ERROR_CLASS = "root-error-class";
+ public static final String ERROR_CLASS = "error-class";
+
@JsonProperty("metadata")
public ErrorMetadata metadata;
@@ -43,11 +47,11 @@ public class ErrorInfo implements JacksonReflectMapWriter {
@JsonProperty("code")
public Integer code;
- public static class ErrorMetadata implements JacksonReflectMapWriter {
- @JsonProperty(SolrException.ERROR_CLASS)
+ public static class ErrorMetadata implements ReflectWritable {
+ @JsonProperty(ERROR_CLASS)
public String errorClass;
- @JsonProperty(SolrException.ROOT_ERROR_CLASS)
+ @JsonProperty(ROOT_ERROR_CLASS)
public String rootErrorClass;
}
}
diff --git a/solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/SolrJerseyResponse.java
similarity index 86%
rename from solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java
rename to solr/api/src/java/org/apache/solr/client/api/model/SolrJerseyResponse.java
index 770fc1eec53..59e528c91f8 100644
--- a/solr/core/src/java/org/apache/solr/jersey/SolrJerseyResponse.java
+++ b/solr/api/src/java/org/apache/solr/client/api/model/SolrJerseyResponse.java
@@ -6,7 +6,7 @@
* (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
+ * 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,
@@ -15,13 +15,14 @@
* limitations under the License.
*/
-package org.apache.solr.jersey;
+package org.apache.solr.client.api.model;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.HashMap;
import java.util.Map;
+import org.apache.solr.client.api.util.ReflectWritable;
/**
* Base response-body POJO to be used by Jersey resources.
@@ -29,7 +30,7 @@
*
Contains fields common to all Solr API responses, particularly the 'responseHeader' and
* 'error' fields.
*/
-public class SolrJerseyResponse implements JacksonReflectMapWriter {
+public class SolrJerseyResponse implements ReflectWritable {
@JsonProperty("responseHeader")
public ResponseHeader responseHeader = new ResponseHeader();
@@ -37,7 +38,7 @@ public class SolrJerseyResponse implements JacksonReflectMapWriter {
@JsonProperty("error")
public ErrorInfo error;
- public static class ResponseHeader implements JacksonReflectMapWriter {
+ public static class ResponseHeader implements ReflectWritable {
@JsonProperty("status")
public int status;
diff --git a/solr/core/src/java/org/apache/solr/jersey/SubResponseAccumulatingJerseyResponse.java b/solr/api/src/java/org/apache/solr/client/api/model/SubResponseAccumulatingJerseyResponse.java
similarity index 98%
rename from solr/core/src/java/org/apache/solr/jersey/SubResponseAccumulatingJerseyResponse.java
rename to solr/api/src/java/org/apache/solr/client/api/model/SubResponseAccumulatingJerseyResponse.java
index a0f0dbfb0e2..5031f86c3a5 100644
--- a/solr/core/src/java/org/apache/solr/jersey/SubResponseAccumulatingJerseyResponse.java
+++ b/solr/api/src/java/org/apache/solr/client/api/model/SubResponseAccumulatingJerseyResponse.java
@@ -15,7 +15,7 @@
* limitations under the License.
*/
-package org.apache.solr.jersey;
+package org.apache.solr.client.api.model;
import com.fasterxml.jackson.annotation.JsonProperty;
diff --git a/solr/api/src/java/org/apache/solr/client/api/model/package-info.java b/solr/api/src/java/org/apache/solr/client/api/model/package-info.java
new file mode 100644
index 00000000000..4264373269c
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/model/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * 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.
+ */
+
+/**
+ * POJOs representing various inputs and outputs of the v2 APIs described in {@link
+ * org.apache.solr.client.api.endpoint}
+ */
+package org.apache.solr.client.api.model;
diff --git a/solr/api/src/java/org/apache/solr/client/api/package-info.java b/solr/api/src/java/org/apache/solr/client/api/package-info.java
new file mode 100644
index 00000000000..aa44ba957da
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** Root package for interfaces and POJOs used to describe Solr's v2 APIs */
+package org.apache.solr.client.api;
diff --git a/solr/api/src/java/org/apache/solr/client/api/util/ApiMetadata.java b/solr/api/src/java/org/apache/solr/client/api/util/ApiMetadata.java
new file mode 100644
index 00000000000..11a70a916d3
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/util/ApiMetadata.java
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.util;
+
+import io.swagger.v3.oas.annotations.OpenAPIDefinition;
+import io.swagger.v3.oas.annotations.info.Info;
+import io.swagger.v3.oas.annotations.info.License;
+
+@OpenAPIDefinition(
+ info =
+ @Info(
+ title = "v2 API",
+ description = "OpenAPI spec for Solr's v2 API endpoints",
+ license = @License(name = "ASL 2.0"),
+ version = SolrVersion.LATEST_STRING))
+public class ApiMetadata {}
diff --git a/solr/api/src/java/org/apache/solr/client/api/util/Constants.java b/solr/api/src/java/org/apache/solr/client/api/util/Constants.java
new file mode 100644
index 00000000000..1dbd6e61a6c
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/util/Constants.java
@@ -0,0 +1,26 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.util;
+
+public class Constants {
+ private Constants() {
+ /* Private ctor prevents instantiation */
+ }
+
+ public static final String BINARY_CONTENT_TYPE_V2 = "application/vnd.apache.solr.javabin";
+}
diff --git a/solr/api/src/java/org/apache/solr/client/api/util/ReflectWritable.java b/solr/api/src/java/org/apache/solr/client/api/util/ReflectWritable.java
new file mode 100644
index 00000000000..bad94276747
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/util/ReflectWritable.java
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.client.api.util;
+
+/**
+ * A marker interface used by v2 POJOs to indicate they contain annotations that can be written out
+ * via reflection.
+ *
+ *
Used primarily by custom serialization/deserialization codepaths that don't natively recognize
+ * (e.g.) Jackson annotations.
+ */
+public interface ReflectWritable {}
diff --git a/solr/core/src/java/org/apache/solr/util/SolrVersion.java b/solr/api/src/java/org/apache/solr/client/api/util/SolrVersion.java
similarity index 90%
rename from solr/core/src/java/org/apache/solr/util/SolrVersion.java
rename to solr/api/src/java/org/apache/solr/client/api/util/SolrVersion.java
index 6661e9e891c..434bbea9596 100644
--- a/solr/core/src/java/org/apache/solr/util/SolrVersion.java
+++ b/solr/api/src/java/org/apache/solr/client/api/util/SolrVersion.java
@@ -14,10 +14,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-package org.apache.solr.util;
+package org.apache.solr.client.api.util;
import java.util.Locale;
-import org.apache.solr.common.SolrException;
import org.semver4j.Semver;
/**
@@ -45,6 +44,14 @@ public static SolrVersion forIntegers(int major, int minor, int patch) {
return new SolrVersion(new Semver(String.format(Locale.ROOT, "%d.%d.%d", major, minor, patch)));
}
+ /**
+ * Compares two versions v1 and v2. Returns negative if v1 isLessThan v2, positive if v1
+ * isGreaterThan v2 and 0 if equal.
+ */
+ public static int compareVersions(String v1, String v2) {
+ return new Semver(v1).compareTo(new Semver(v2));
+ }
+
/** Return version as plain SemVer string, e.g. "9.0.1" */
@Override
public String toString() {
@@ -118,13 +125,4 @@ public boolean equals(Object other) {
}
return compareTo((SolrVersion) other) == 0;
}
-
- public static class InvalidSemVerExpressionException extends SolrException {
- public InvalidSemVerExpressionException(Exception exception, String expression) {
- super(
- ErrorCode.BAD_REQUEST,
- String.format(Locale.ROOT, "Invalid SemVer expression: %s", expression),
- exception);
- }
- }
}
diff --git a/solr/api/src/java/org/apache/solr/client/api/util/package-info.java b/solr/api/src/java/org/apache/solr/client/api/util/package-info.java
new file mode 100644
index 00000000000..c7634ce945c
--- /dev/null
+++ b/solr/api/src/java/org/apache/solr/client/api/util/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** Utilities for working with Solr api interfaces and model classes. */
+package org.apache.solr.client.api.util;
diff --git a/solr/core/src/test/org/apache/solr/util/TestSolrVersion.java b/solr/api/src/test/org/apache/solr/util/TestSolrVersion.java
similarity index 97%
rename from solr/core/src/test/org/apache/solr/util/TestSolrVersion.java
rename to solr/api/src/test/org/apache/solr/util/TestSolrVersion.java
index 1a43e7cab71..ff55514e4ab 100644
--- a/solr/core/src/test/org/apache/solr/util/TestSolrVersion.java
+++ b/solr/api/src/test/org/apache/solr/util/TestSolrVersion.java
@@ -17,6 +17,7 @@
package org.apache.solr.util;
import org.apache.solr.SolrTestCase;
+import org.apache.solr.client.api.util.SolrVersion;
import org.semver4j.SemverException;
public class TestSolrVersion extends SolrTestCase {
diff --git a/solr/core/build.gradle b/solr/core/build.gradle
index 83f48e2f223..d868164cd75 100644
--- a/solr/core/build.gradle
+++ b/solr/core/build.gradle
@@ -15,20 +15,10 @@
* limitations under the License.
*/
-plugins {
- id 'io.swagger.core.v3.swagger-gradle-plugin' version '2.2.2'
-}
-
apply plugin: 'java-library'
description = 'Apache Solr Core'
-resolve {
- classpath = sourceSets.main.runtimeClasspath
- outputDir = file("build/generated/openapi")
- prettyPrint = true
-}
-
dependencies {
// Spotbugs Annotations are only needed for old findbugs
// annotation usage like in Zookeeper during compilation time.
@@ -54,6 +44,7 @@ dependencies {
// We export logging api with dependencies, which is useful for all modules
api 'org.slf4j:slf4j-api'
+ api project(':solr:api')
api project(':solr:solrj')
api project(':solr:solrj-zookeeper')
api project(':solr:solrj-streaming')
@@ -142,9 +133,6 @@ dependencies {
// required for instantiating a Zookeeper server (for embedding ZK or running tests)
runtimeOnly ('org.xerial.snappy:snappy-java')
- // For Package Manager
- implementation 'org.semver4j:semver4j'
-
implementation('com.jayway.jsonpath:json-path', {
exclude group: "net.minidev", module: "json-smart"
})
diff --git a/solr/core/src/java/org/apache/solr/api/JerseyResource.java b/solr/core/src/java/org/apache/solr/api/JerseyResource.java
index e96216e170e..6a304654e27 100644
--- a/solr/core/src/java/org/apache/solr/api/JerseyResource.java
+++ b/solr/core/src/java/org/apache/solr/api/JerseyResource.java
@@ -22,9 +22,9 @@
import java.util.function.Supplier;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.core.Context;
+import org.apache.solr.client.api.model.SolrJerseyResponse;
import org.apache.solr.common.SolrException;
import org.apache.solr.jersey.CatchAllExceptionMapper;
-import org.apache.solr.jersey.SolrJerseyResponse;
import org.apache.solr.servlet.HttpSolrCall;
/**
diff --git a/solr/core/src/java/org/apache/solr/cli/SimplePostTool.java b/solr/core/src/java/org/apache/solr/cli/SimplePostTool.java
index 11478366711..d15650e1636 100644
--- a/solr/core/src/java/org/apache/solr/cli/SimplePostTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/SimplePostTool.java
@@ -65,9 +65,9 @@
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
+import org.apache.solr.client.api.util.SolrVersion;
import org.apache.solr.common.util.Utils;
import org.apache.solr.util.RTimer;
-import org.apache.solr.util.SolrVersion;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
diff --git a/solr/core/src/java/org/apache/solr/cli/VersionTool.java b/solr/core/src/java/org/apache/solr/cli/VersionTool.java
index 1b0e1fa4644..f5e84e6c1f8 100644
--- a/solr/core/src/java/org/apache/solr/cli/VersionTool.java
+++ b/solr/core/src/java/org/apache/solr/cli/VersionTool.java
@@ -21,7 +21,7 @@
import java.util.List;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.Option;
-import org.apache.solr.util.SolrVersion;
+import org.apache.solr.client.api.util.SolrVersion;
public class VersionTool extends ToolBase {
diff --git a/solr/core/src/java/org/apache/solr/handler/IncrementalShardBackup.java b/solr/core/src/java/org/apache/solr/handler/IncrementalShardBackup.java
index 74128375ad0..c4de4807588 100644
--- a/solr/core/src/java/org/apache/solr/handler/IncrementalShardBackup.java
+++ b/solr/core/src/java/org/apache/solr/handler/IncrementalShardBackup.java
@@ -29,6 +29,7 @@
import org.apache.commons.math3.util.Precision;
import org.apache.lucene.index.IndexCommit;
import org.apache.lucene.store.Directory;
+import org.apache.solr.client.api.model.SolrJerseyResponse;
import org.apache.solr.cloud.CloudDescriptor;
import org.apache.solr.common.SolrException;
import org.apache.solr.core.DirectoryFactory;
@@ -39,7 +40,6 @@
import org.apache.solr.core.backup.ShardBackupId;
import org.apache.solr.core.backup.ShardBackupMetadata;
import org.apache.solr.core.backup.repository.BackupRepository;
-import org.apache.solr.jersey.SolrJerseyResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
index f49ef231f9e..9f6d09bab22 100644
--- a/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
+++ b/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
@@ -66,6 +66,7 @@
import org.apache.lucene.store.IndexInput;
import org.apache.lucene.store.RateLimiter;
import org.apache.solr.api.JerseyResource;
+import org.apache.solr.client.api.model.SolrJerseyResponse;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.params.CommonParams;
@@ -91,7 +92,6 @@
import org.apache.solr.handler.IndexFetcher.IndexFetchResult;
import org.apache.solr.handler.admin.api.CoreReplicationAPI;
import org.apache.solr.handler.api.V2ApiUtils;
-import org.apache.solr.jersey.SolrJerseyResponse;
import org.apache.solr.metrics.MetricsMap;
import org.apache.solr.metrics.SolrMetricsContext;
import org.apache.solr.request.SolrQueryRequest;
diff --git a/solr/core/src/java/org/apache/solr/handler/SnapShooter.java b/solr/core/src/java/org/apache/solr/handler/SnapShooter.java
index 184d2aeb0c2..4f2beb51983 100644
--- a/solr/core/src/java/org/apache/solr/handler/SnapShooter.java
+++ b/solr/core/src/java/org/apache/solr/handler/SnapShooter.java
@@ -35,6 +35,7 @@
import java.util.function.Consumer;
import org.apache.lucene.index.IndexCommit;
import org.apache.lucene.store.Directory;
+import org.apache.solr.client.api.model.SolrJerseyResponse;
import org.apache.solr.common.SolrException;
import org.apache.solr.common.SolrException.ErrorCode;
import org.apache.solr.common.util.NamedList;
@@ -47,7 +48,6 @@
import org.apache.solr.core.backup.repository.LocalFileSystemRepository;
import org.apache.solr.core.snapshots.SolrSnapshotMetaDataManager;
import org.apache.solr.handler.api.V2ApiUtils;
-import org.apache.solr.jersey.SolrJerseyResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
diff --git a/solr/core/src/java/org/apache/solr/handler/admin/BackupCoreOp.java b/solr/core/src/java/org/apache/solr/handler/admin/BackupCoreOp.java
index 2f5407416c4..bfd939c43b4 100644
--- a/solr/core/src/java/org/apache/solr/handler/admin/BackupCoreOp.java
+++ b/solr/core/src/java/org/apache/solr/handler/admin/BackupCoreOp.java
@@ -25,7 +25,6 @@
import org.apache.solr.core.backup.ShardBackupId;
import org.apache.solr.handler.admin.api.BackupCoreAPI;
import org.apache.solr.handler.api.V2ApiUtils;
-import org.apache.solr.jersey.SolrJerseyResponse;
class BackupCoreOp implements CoreAdminHandler.CoreAdminOp {
@@ -53,7 +52,7 @@ public void execute(CoreAdminHandler.CallInfo it) throws Exception {
new BackupCoreAPI(
it.handler.coreContainer, it.req, it.rsp, it.handler.coreAdminAsyncTracker);
try {
- SolrJerseyResponse response = backupCoreAPI.createBackup(cname, backupCoreRequestBody);
+ final var response = backupCoreAPI.createBackup(cname, backupCoreRequestBody);
NamedList