Skip to content

Migrate Schema Designer to JAX-RS Apis. Fix some bugs.#4203

Open
epugh wants to merge 33 commits intoapache:mainfrom
epugh:copilot/migrate-schemadesignerapi-to-v2-annotations
Open

Migrate Schema Designer to JAX-RS Apis. Fix some bugs.#4203
epugh wants to merge 33 commits intoapache:mainfrom
epugh:copilot/migrate-schemadesignerapi-to-v2-annotations

Conversation

@epugh
Copy link
Copy Markdown
Contributor

@epugh epugh commented Mar 10, 2026

Summary

Migrate the SchemaDesigner to JAX-RS. Fixed a bug in the analyze feature that wasn't working in main.

Changes

JAX-RS adoption, RESTful style routing, and code review. Had to change up the routes in the JavaScript to match.

The runtime behaviour is unchanged.

Copilot AI and others added 8 commits February 22, 2026 14:50
Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…mments

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…y docs guard)

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…ader, sanitize filename

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…/docs map for JS rendering

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
@epugh epugh requested a review from Copilot March 10, 2026 09:50
@epugh epugh changed the title Fix unchecked cast warning in DefaultSampleDocumentsLoader Migrate Schema Designer to Ja Mar 10, 2026
@epugh epugh changed the title Migrate Schema Designer to Ja Migrate Schema Designer to JAX-RS Apis. Fix some bugs. Mar 10, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR refactors the Schema Designer v2 API implementation to a Jersey-based resource + OpenAPI-defined interface, updates the admin UI download URL accordingly, and includes a small improvement to JSON-lines parsing to avoid unchecked-cast warnings.

Changes:

  • Migrate SchemaDesignerAPI from the legacy @EndPoint style to a JerseyResource implementing a new SchemaDesignerApi interface, and update tests to call the new method signatures.
  • Adjust the Schema Designer UI download endpoint URL to the new /api/schema-designer/download?configSet=... form.
  • Narrow unchecked-cast suppression in DefaultSampleDocumentsLoader via a helper method using instanceof Map<?, ?>.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
solr/webapp/web/js/angular/controllers/schema-designer.js Updates Schema Designer download URL to new endpoint shape.
solr/core/src/test/org/apache/solr/handler/designer/TestSchemaDesignerAPI.java Reworks tests to call new Jersey-style API methods and response handling.
solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerSettings.java Changes settings class visibility to public.
solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerConstants.java Removes unused constants related to old request-param handling.
solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerConfigSetHelper.java Minor cleanup/modernization and removal of unused helper logic.
solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerAPI.java Major migration to JerseyResource + SchemaDesignerApi, plus download/query response changes.
solr/core/src/java/org/apache/solr/handler/designer/SampleDocuments.java Uses Stream.toList() instead of Collectors.toList().
solr/core/src/java/org/apache/solr/handler/designer/DefaultSchemaSuggester.java Adjusts field-prop guessing API/signature usage.
solr/core/src/java/org/apache/solr/handler/designer/DefaultSampleDocumentsLoader.java Introduces parseStringToJson() helper and narrows unchecked-cast suppression.
solr/core/src/java/org/apache/solr/core/CoreContainer.java Registers Schema Designer as a Jersey resource class.
solr/api/src/java/org/apache/solr/client/api/endpoint/SchemaDesignerApi.java Adds new OpenAPI/JAX-RS interface defining Schema Designer endpoints.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines 822 to 826
if (errorsDuringIndexing != null) {
Map<String, Object> response = new HashMap<>();
rsp.setException(
new SolrException(
SolrException.ErrorCode.BAD_REQUEST,
"Failed to re-index sample documents after schema updated."));
response.put(ERROR_DETAILS, errorsDuringIndexing);
rsp.getValues().addAll(response);
return;
throw new SolrException(
SolrException.ErrorCode.BAD_REQUEST,
"Failed to re-index sample documents after schema updated.");
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

query() used to return an error response containing errorDetails when re-indexing failed, which the Schema Designer UI surfaces (see its errorHandler). This new implementation throws a SolrException without attaching errorDetails, so clients will lose the per-doc failure details. Consider instantiating a FlexibleSolrJerseyResponse early and setting an errorDetails top-level property before throwing, or otherwise preserve the prior error payload structure.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks, I dug in and found some bugs and fixed them in how we surface errors.
image

Comment on lines +1349 to 1354
protected void requireSchemaVersion(Integer schemaVersion) {
if (schemaVersion == null) {
throw new SolrException(
SolrException.ErrorCode.BAD_REQUEST,
SCHEMA_VERSION_PARAM + " is a required parameter for the " + req.getPath() + " endpoint");
SolrException.ErrorCode.BAD_REQUEST, SCHEMA_VERSION_PARAM + " is a required parameter!");
}
return schemaVersion;
}
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

requireSchemaVersion() now only rejects null, but previously the API treated -1 as “missing” (since getInt(..., -1) was used) and rejected it. As written, a client can pass schemaVersion=-1 and bypass this validation; it would be safer to also reject negative values to keep the same contract.

Copilot uses AI. Check for mistakes.
@epugh epugh requested review from dsmiley and janhoy March 10, 2026 10:43
Copilot AI and others added 3 commits March 19, 2026 11:57
…sentinel contract)

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
… github.com:epugh/solr into copilot/migrate-schemadesignerapi-to-v2-annotations
@epugh
Copy link
Copy Markdown
Contributor Author

epugh commented Mar 21, 2026

Discussing with @gerlowskija this ticket, and he brings up the "Shouldn't this be more restFul"? Looking at it, configSet is a query param in ALL of these, and really should be part of the path param.

@epugh
Copy link
Copy Markdown
Contributor Author

epugh commented Mar 30, 2026

image image

@epugh epugh requested a review from gerlowskija March 30, 2026 10:10
Copy link
Copy Markdown
Contributor

@gerlowskija gerlowskija left a comment

Choose a reason for hiding this comment

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

Just started looking through this and had a few initial comments.

I'm really hesitant to ask larger questions about these schema-designer APIs that would really bog down this PR. But to toe the line on that front: so many of these APIs (e.g. GET /schema-designer/configs, DELETE /schema-designer/<configset>) look nearly identical to CRUD APIs that already exist for configsets. Which seems at least somewhat suspect...

Maybe we're better off holding off on any REST-ful-ness changes in this PR, so that we can give some of those questions the time/attention they deserve rather than lumping them in here?

@@ -0,0 +1,8 @@
# See https://github.com/apache/solr/blob/main/dev-docs/changelog.adoc
title: Migrate Schema Designer API to JAX-RS. Fix bug preventing analysis of sample documents from running.
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.

[-0] This is user-facing text - why would a user care what framework we use in our server-side code?

For most APIs I generally make the changelog entry about the new SolrJ SolrRequest/SolrResponse that'll be generated. That may make sense here as well? But also - these APIs are so UI-centric that it's hard to imagine anyone ever calling them from Java code. Without a use case there, even that sort of a changelog entry might not make sense...

Maybe the changelog here should "just" highlight the bug fix and give a bit more detail on that?

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.

Copy link
Copy Markdown
Contributor

@gerlowskija gerlowskija left a comment

Choose a reason for hiding this comment

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

Alright - I've still largely held off from reviewing the actual cosmetics of the APIs laid out in SchemaDesignerApi (and correspondingly skipped the '.js' files).

But otherwise I've reviewed most of this and highlighted a handful of things that probably need changed here to fit with how we've been using JAX-RS elsewhere. Lmk if you have any questions!

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.

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.

@Operation(
summary = "Get info about a configSet being designed.",
tags = {"schema-designer"})
FlexibleSolrJerseyResponse getInfo(@PathParam("configSet") String configSet) throws Exception;
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.

[-0] Why use 'FlexibleSolrJerseyResponse' here as opposed to some more tailored POJO type? AFAICT from the implementing code, the response has 4 or 5 top-level properties and modeling as a POJO should be pretty doable.

Ditto for several of the other endpoints here as well.


private void parseStringToJson(List<Map<String, Object>> docs, String line) throws IOException {
line = line.trim();
if (line.startsWith("{") && line.endsWith("}")) {
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] Previous version had !line.isEmpty() condition here. Is there a reason that was removed?

List<Object> sampleValues,
boolean isMV,
IndexSchema schema) {
String fieldName, FieldType fieldType, boolean isMV, IndexSchema schema) {
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.

[0] Is this just an opportunistic refactor that removes an unused parameter (i.e. 'sampleValues')?

I'm fine with this one, but in future I'd prefer if you leave these out of these "purely JAX-RS migration" PRs. Just makes the diff harder to read and opens the door to subtle bugs slipping in, is all.

&& !ids.contains(id); // doc has ID, and it's not already in the set
})
.collect(Collectors.toList());
.toList();
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.

Ditto, re: unrelated tweaks/refactors making this harder to review and vet.

int rf = req.getParams().getInt("replicationFactor", 1);
configSetHelper.createCollection(newCollection, configSet, numShards, rf);
if (req.getParams().getBool(INDEX_TO_COLLECTION_PARAM, false)) {
configSetHelper.createCollection(newCollection, configSet, numShards, replicationFactor);
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.

[-1] Ditto, re: triggering an NPE if 'numShards', 'replicationFactor', etc. aren't specified.

The existing code uses particular defaults (1) here as well that we should probably be making sure the newer code uses

qr.getResponse()
.forEach(
(name, val) -> {
if ("response".equals(name) && val instanceof SolrDocumentList) {
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] Can you add some context on this part of the PR please?

@@ -1106,7 +1162,7 @@ protected long waitToSeeSampleDocs(String collectionName, long numAdded)
return numFound;
}

protected Map<String, Object> buildResponse(
Map<String, Object> buildResponse(
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] Why the visibility change?

@@ -1260,8 +1316,7 @@ protected Map<String, Object> readJsonFromRequest(SolrQueryRequest req) throws I
return (Map<String, Object>) json;
}

protected void addSettingsToResponse(
SchemaDesignerSettings settings, final Map<String, Object> response) {
void addSettingsToResponse(SchemaDesignerSettings settings, final Map<String, Object> response) {
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] Why the visibility-changes on some of these methods?

.filter(df -> langFieldTypeNames.contains(df.getPrototype().getType().getTypeName()))
.filter(df -> !existingDynFields.contains(df.getPrototype().getName()))
.map(IndexSchema.DynamicField::getPrototype)
.filter(prototype -> langFieldTypeNames.contains(prototype.getType().getTypeName()))
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] What's the rationale for moving this down below the map(...). It seems unrelated to the JAX-RS migration unless I'm missing something?

Copilot AI and others added 15 commits April 2, 2026 14:47
…playName query param

Agent-Logs-Url: https://github.com/epugh/solr/sessions/eff3e08e-97a3-4e83-832c-74cc41e9058d

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
Replace all FlexibleSolrJerseyResponse usages with the specific typed
response POJOs (SchemaDesignerResponse, SchemaDesignerInfoResponse,
SchemaDesignerCollectionsResponse, SchemaDesignerSchemaDiffResponse)
returned by the SchemaDesigner API methods.

Also fix SchemaDesigner.setSchemaObjectField() to handle the add-field
and add-field-type action names used by the Schema API request JSON, so
that response.field is populated for add-field requests and
response.fieldType for add-field-type requests.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…i-to-v2-annotations' into copilot/migrate-schemadesignerapi-to-v2-annotations

# Conflicts:
#	solr/core/src/java/org/apache/solr/handler/configsets/DownloadConfigSet.java

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…s $resource in JS

Agent-Logs-Url: https://github.com/epugh/solr/sessions/adec0806-852d-4a34-a0fb-aef713d8bf76

Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants