Migrate Schema Designer to JAX-RS Apis. Fix some bugs.#4203
Migrate Schema Designer to JAX-RS Apis. Fix some bugs.#4203epugh wants to merge 33 commits intoapache:mainfrom
Conversation
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>
There was a problem hiding this comment.
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
SchemaDesignerAPIfrom the legacy@EndPointstyle to aJerseyResourceimplementing a newSchemaDesignerApiinterface, 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
DefaultSampleDocumentsLoadervia a helper method usinginstanceof 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.
| 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."); | ||
| } |
There was a problem hiding this comment.
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.
| 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; | ||
| } |
There was a problem hiding this comment.
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.
solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerSettings.java
Outdated
Show resolved
Hide resolved
solr/core/src/java/org/apache/solr/handler/designer/SchemaDesignerAPI.java
Outdated
Show resolved
Hide resolved
…sentinel contract) Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…emadesignerapi-to-v2-annotations
… github.com:epugh/solr into copilot/migrate-schemadesignerapi-to-v2-annotations
|
Discussing with @gerlowskija this ticket, and he brings up the "Shouldn't this be more restFul"? Looking at it, |
…ner API Agent-Logs-Url: https://github.com/epugh/solr/sessions/3e11a7a9-caca-4333-8a6b-bbcd5a2cd862 Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
Agent-Logs-Url: https://github.com/epugh/solr/sessions/8f08e90a-243e-43eb-9aaf-070c2e9ed092 Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
gerlowskija
left a comment
There was a problem hiding this comment.
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. | |||
There was a problem hiding this comment.
[-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") |
There was a problem hiding this comment.
[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?
There was a problem hiding this comment.
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.
gerlowskija
left a comment
There was a problem hiding this comment.
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") |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
[-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("}")) { |
There was a problem hiding this comment.
[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) { |
There was a problem hiding this comment.
[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(); |
There was a problem hiding this comment.
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); |
There was a problem hiding this comment.
[-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) { |
There was a problem hiding this comment.
[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( | |||
There was a problem hiding this comment.
[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) { | |||
There was a problem hiding this comment.
[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())) |
There was a problem hiding this comment.
[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?
…igSet Agent-Logs-Url: https://github.com/epugh/solr/sessions/b4bd2d0e-f388-4fa4-8e0a-6df9ef796863 Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
changelog/unreleased/SOLR-18152-add-configset-download-zip-to-solrj-fix-schema-designer-bug.yml
Show resolved
Hide resolved
…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>
…r API Agent-Logs-Url: https://github.com/epugh/solr/sessions/507f5cc3-13ae-4824-a6c1-ef4f98052d35 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>
Agent-Logs-Url: https://github.com/epugh/solr/sessions/b74e99f0-20cb-45c6-afa8-b2acdd295385 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>
… tests Agent-Logs-Url: https://github.com/epugh/solr/sessions/10ac2a78-7ae6-44d5-858d-e74dd03593ea Co-authored-by: epugh <22395+epugh@users.noreply.github.com>



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.