Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
8812129
Initial plan
Copilot Feb 22, 2026
42395bc
Migrate SchemaDesignerAPI to JAX-RS V2 annotations
Copilot Feb 22, 2026
20f4431
Address code review feedback: fix copyFrom parameter shadowing and co…
Copilot Feb 22, 2026
de90529
Fix query() returning no results when sample docs not in memory (empt…
Copilot Feb 22, 2026
912c762
Fix schema designer download: correct URL, add Content-Disposition he…
Copilot Feb 23, 2026
7c16593
Fix query response structure: wrap SolrDocumentList in numFound/start…
Copilot Feb 23, 2026
b382a4c
Lint clean ups. "multivalued" is how we spell it ;-) Not "multi-val…
epugh Mar 6, 2026
233162e
code review and manual testing
epugh Mar 10, 2026
11f5209
track change
epugh Mar 10, 2026
6a46d40
Finally fix the visibility warning!
epugh Mar 10, 2026
bcb6a86
Restore surfacing indexing errors.
epugh Mar 10, 2026
115fccb
Fix error prone.
epugh Mar 10, 2026
6756865
Fix requireSchemaVersion to also reject negative values (restores -1 …
Copilot Mar 19, 2026
c7e0099
Merge remote-tracking branch 'upstream/main' into copilot/migrate-sch…
epugh Mar 19, 2026
810cb96
Merge branch 'copilot/migrate-schemadesignerapi-to-v2-annotations' of…
epugh Mar 19, 2026
c04147f
Move configSet from query parameter to path parameter in Schema Desig…
Copilot Mar 30, 2026
7f6274c
Use correct HTTP verbs in Schema Designer API (DELETE and PUT)
Copilot Mar 30, 2026
d05be2f
Move downloadConfig to reusable ConfigsetsApi.Download / DownloadConf…
Copilot Apr 2, 2026
0881dba
Move schema-designer download to generic configsets endpoint; add dis…
Copilot Apr 2, 2026
b021f15
Use our standard naming pattern that the Api is in the endpoint package
epugh Apr 2, 2026
9667896
Rework changelog
epugh Apr 2, 2026
91be03c
Use same style for all class intro javadocs.
epugh Apr 2, 2026
a3befe4
Update TestSchemaDesigner to use typed POJO return types
Copilot Apr 2, 2026
0520952
Add clarifying comment to setSchemaObjectField switch
Copilot Apr 2, 2026
9e3f38d
Replace FlexibleSolrJerseyResponse with typed POJOs in Schema Designe…
Copilot Apr 2, 2026
b52c891
Merge remote-tracking branch 'origin/copilot/migrate-schemadesignerap…
Copilot Apr 2, 2026
f53de8f
Add BATS integration test for Schema Designer API endpoints
Copilot Apr 2, 2026
13a2abf
Move getFileContents to ConfigsetsApi/GetConfigSetFile; add Configset…
Copilot Apr 2, 2026
b6a69de
Reduce mocking: use real FileSystemConfigSetService in configsets API…
Copilot Apr 2, 2026
42db2a3
Mention new capablities in solrj in changelog
epugh Apr 3, 2026
ac0a661
code review
epugh Apr 3, 2026
96efd9d
More test coverage
epugh Apr 3, 2026
46d3042
Prevent warning
epugh Apr 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
title: The "analyze" existing documents feature of Schema Designer was fixed. Added a new ConfigSet.Download and ConfigSet.GetFile capablities to SolrJ.
type: fixed # added, changed, fixed, deprecated, removed, dependency_update, security, other
authors:
- name: Eric Pugh
links:
- name: SOLR-18152
url: https://issues.apache.org/jira/browse/SOLR-18152
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,26 @@
*/
package org.apache.solr.client.api.endpoint;

import static org.apache.solr.client.api.util.Constants.RAW_OUTPUT_PROPERTY;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;
import io.swagger.v3.oas.annotations.parameters.RequestBody;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import java.io.IOException;
import java.io.InputStream;
import org.apache.solr.client.api.model.CloneConfigsetRequestBody;
import org.apache.solr.client.api.model.ConfigSetFileContentsResponse;
import org.apache.solr.client.api.model.ListConfigsetsResponse;
import org.apache.solr.client.api.model.SolrJerseyResponse;

Expand Down Expand Up @@ -71,6 +79,46 @@ SolrJerseyResponse deleteConfigSet(@PathParam("configSetName") String configSetN
throws Exception;
}

/**
* V2 API definition for downloading an existing configset as a ZIP archive.
*
* <p>Equivalent to GET /api/configsets/{configSetName}/download
*/
@Path("/configsets/{configSetName}")
interface Download {
@GET
@Path("/download")
@Operation(
summary = "Download a configset as a ZIP archive.",
tags = {"configsets"},
extensions = {
@Extension(properties = {@ExtensionProperty(name = RAW_OUTPUT_PROPERTY, value = "true")})
})
@Produces("application/zip")
Response downloadConfigSet(
@PathParam("configSetName") String configSetName,
@QueryParam("displayName") String displayName)
throws Exception;
}

/**
* V2 API definition for reading a single file from an existing configset.
*
* <p>Equivalent to GET /api/configsets/{configSetName}/file?path=...
*/
@Path("/configsets/{configSetName}")
interface GetFile {
@GET
@Path("/file")
@Produces(MediaType.TEXT_PLAIN)
@Operation(
summary = "Get the contents of a file in a configset.",
tags = {"configsets"})
ConfigSetFileContentsResponse getConfigSetFile(
@PathParam("configSetName") String configSetName, @QueryParam("path") String filePath)
throws Exception;
}

/**
* V2 API definitions for uploading a configset, in whole or part.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.solr.client.api.endpoint;

import io.swagger.v3.oas.annotations.Operation;
import jakarta.ws.rs.DELETE;
import jakarta.ws.rs.DefaultValue;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.PUT;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.QueryParam;
import java.util.List;
import org.apache.solr.client.api.model.FlexibleSolrJerseyResponse;
import org.apache.solr.client.api.model.SchemaDesignerCollectionsResponse;
import org.apache.solr.client.api.model.SchemaDesignerConfigsResponse;
import org.apache.solr.client.api.model.SchemaDesignerInfoResponse;
import org.apache.solr.client.api.model.SchemaDesignerPublishResponse;
import org.apache.solr.client.api.model.SchemaDesignerResponse;
import org.apache.solr.client.api.model.SchemaDesignerSchemaDiffResponse;
import org.apache.solr.client.api.model.SolrJerseyResponse;

/** V2 API definitions for the Solr Schema Designer. */
@Path("/schema-designer")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[Q] This comment aims to summarize the cosmetic changes you've made here. But that comment itself looks off somehow.

Looking at the actual code here, each API has a /schema-designer path prefix that just isn't mentioned in the proposal at all.

Further the "Before" column doesn't appear to actually represent the APIs as they exist today on main. Rather the column appears to represent some intermediate state in your PR's development (i.e. after you moved the configset param in to the path). Which is kindof misleading in terms of understanding the "net" change being proposed.

Was this intentional? (e.g. /schema-designer was omitted for concise-ness) Or am I maybe missing something here?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to largely skip review of this file for now given some of the uncertainties above, but happy to review those later on.

public interface SchemaDesignerApi {

@GET
@Path("/{configSet}/info")
@Operation(
summary = "Get info about a configSet being designed.",
tags = {"schema-designer"})
SchemaDesignerInfoResponse getInfo(@PathParam("configSet") String configSet) throws Exception;

@POST
@Path("/{configSet}/prep")
@Operation(
summary = "Prepare a mutable configSet copy for schema design.",
tags = {"schema-designer"})
SchemaDesignerResponse prepNewSchema(
@PathParam("configSet") String configSet, @QueryParam("copyFrom") String copyFrom)
throws Exception;

@DELETE
@Path("/{configSet}")
@Operation(
summary = "Clean up temporary resources for a schema being designed.",
tags = {"schema-designer"})
SolrJerseyResponse cleanupTempSchema(@PathParam("configSet") String configSet) throws Exception;

@PUT
@Path("/{configSet}/file")
@Operation(
summary = "Update the contents of a file in a configSet being designed.",
tags = {"schema-designer"})
SchemaDesignerResponse updateFileContents(
@PathParam("configSet") String configSet, @QueryParam("file") String file) throws Exception;

@GET
@Path("/{configSet}/sample")
@Operation(
summary = "Get a sample value and analysis for a field.",
tags = {"schema-designer"})
FlexibleSolrJerseyResponse getSampleValue(
@PathParam("configSet") String configSet,
@QueryParam("field") String fieldName,
@QueryParam("uniqueKeyField") String idField,
@QueryParam("docId") String docId)
throws Exception;

@GET
@Path("/{configSet}/collectionsForConfig")
@Operation(
summary = "List collections that use a given configSet.",
tags = {"schema-designer"})
SchemaDesignerCollectionsResponse listCollectionsForConfig(
@PathParam("configSet") String configSet) throws Exception;

@GET
@Path("/configs")
@Operation(
summary = "List all configSets available for schema design.",
tags = {"schema-designer"})
SchemaDesignerConfigsResponse listConfigs() throws Exception;

@POST
@Path("/{configSet}/add")
@Operation(
summary = "Add a new field, field type, or dynamic field to the schema being designed.",
tags = {"schema-designer"})
SchemaDesignerResponse addSchemaObject(
@PathParam("configSet") String configSet, @QueryParam("schemaVersion") Integer schemaVersion)
throws Exception;

@PUT
@Path("/{configSet}/update")
@Operation(
summary = "Update an existing field or field type in the schema being designed.",
tags = {"schema-designer"})
SchemaDesignerResponse updateSchemaObject(
@PathParam("configSet") String configSet, @QueryParam("schemaVersion") Integer schemaVersion)
throws Exception;

@PUT
@Path("/{configSet}/publish")
@Operation(
summary = "Publish the designed schema to a live configSet.",
tags = {"schema-designer"})
SchemaDesignerPublishResponse publish(
@PathParam("configSet") String configSet,
@QueryParam("schemaVersion") Integer schemaVersion,
@QueryParam("newCollection") String newCollection,
@QueryParam("reloadCollections") @DefaultValue("false") Boolean reloadCollections,
@QueryParam("numShards") @DefaultValue("1") Integer numShards,
@QueryParam("replicationFactor") @DefaultValue("1") Integer replicationFactor,
@QueryParam("indexToCollection") @DefaultValue("false") Boolean indexToCollection,
@QueryParam("cleanupTemp") @DefaultValue("true") Boolean cleanupTempParam,
@QueryParam("disableDesigner") @DefaultValue("false") Boolean disableDesigner)
throws Exception;

@POST
@Path("/{configSet}/analyze")
@Operation(
summary = "Analyze sample documents and suggest a schema.",
tags = {"schema-designer"})
SchemaDesignerResponse analyze(
@PathParam("configSet") String configSet,
@QueryParam("schemaVersion") Integer schemaVersion,
@QueryParam("copyFrom") String copyFrom,
@QueryParam("uniqueKeyField") String uniqueKeyField,
@QueryParam("languages") List<String> languages,
@QueryParam("enableDynamicFields") Boolean enableDynamicFields,
@QueryParam("enableFieldGuessing") Boolean enableFieldGuessing,
@QueryParam("enableNestedDocs") Boolean enableNestedDocs)
throws Exception;

@GET
@Path("/{configSet}/query")
@Operation(
summary = "Query the temporary collection used during schema design.",
tags = {"schema-designer"})
FlexibleSolrJerseyResponse query(@PathParam("configSet") String configSet) throws Exception;

@GET
@Path("/{configSet}/diff")
@Operation(
summary = "Get the diff between the designed schema and the published schema.",
tags = {"schema-designer"})
SchemaDesignerSchemaDiffResponse getSchemaDiff(@PathParam("configSet") String configSet)
throws Exception;
}
Original file line number Diff line number Diff line change
@@ -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.model;

import com.fasterxml.jackson.annotation.JsonProperty;

/** Response type for the "get configset file contents" API. */
public class ConfigSetFileContentsResponse extends SolrJerseyResponse {

/** The path of the file within the configset (as requested). */
@JsonProperty("path")
public String path;

/** The UTF-8 text content of the file. */
@JsonProperty("content")
public String content;
}
Original file line number Diff line number Diff line change
@@ -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.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.List;

/** Response body for the Schema Designer list-collections-for-config endpoint. */
public class SchemaDesignerCollectionsResponse extends SolrJerseyResponse {

@JsonProperty("collections")
public List<String> collections;
}
Original file line number Diff line number Diff line change
@@ -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.model;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Map;

/** Response body for the Schema Designer list-configs endpoint. */
public class SchemaDesignerConfigsResponse extends SolrJerseyResponse {

/**
* Map of configSet name to status: 0 = in-progress (temp only), 1 = disabled, 2 = enabled and
* published.
*/
@JsonProperty("configSets")
public Map<String, Integer> configSets;
}
Loading
Loading