Repository navigation
Conversation
- Add UpdateApi JAX-RS interface in solr/api module with @path, @post, @operation annotations for /update, /update/json, /update/xml, /update/csv, /update/bin endpoints - Rewrite UpdateAPI as a JerseyResource implementing UpdateApi; delegates to UpdateRequestHandler; adds UpdateRequestHandlerConfig inner class (APIConfigProvider.APIConfig) for injection - Update V2UpdateRequestHandler to implement APIConfigProvider and use getJerseyResources() instead of getApis() - Replace mock-based V2UpdateAPIMappingTest with UpdateAPITest integration test using SolrJettyTestRule Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
Resolves failing test: NodeHealthAPITest2.testLegacyMode_WithoutMaxGenerationLagReturnsOk The test verifies that the V2 GET /api/node/health endpoint returns status=OK in legacy (standalone, non-ZooKeeper) mode when maxGenerationLag is not specified in the request. This exercises the null-maxGenerationLag code path in HealthCheckHandler.healthCheckLegacyMode() which immediately returns OK without checking replication lag. Test uses SolrJettyTestRule with no ZooKeeper to run in legacy mode. Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…n V2Request update/json
The V2Request("/c/{collection}/update/json") call was broken after the UpdateAPI
migration to JAX-RS: the JAX-RS path regex "cores|collections" doesn't match
the "/c/" alias. Replace with the proper SolrJ cloudClient.add() (which goes
through the v1 /update path) and update span name/collection assertions to match.
Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
Normalize /c/ → /collections/ in ContainerRequestUtils.getRequestUri() before
Jersey sees the URI, fixing JAX-RS path matching for all endpoints that use
INDEX_PATH_PREFIX (update, select, schema, etc.) with the /c/ shorthand.
The tracing span name correctly preserves /c/{collection}/... since it is
computed from V2HttpCall.pathSegments which use the original request path.
Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
…o UpdateRequestHandler DistributedZkUpdateProcessor.handleReplicationFactor() calls rsp.getResponseHeader().add(...), which requires the response header to be initialized by SolrCore.preDecorateResponse(). In the JAX-RS path, this was never called (only the old Api path calls it in executeCoreRequest). Add pre/postDecorateResponse calls around the updateRequestHandler.handleRequest() call in UpdateAPI.handleUpdate(), mirroring what SolrCore.execute() does for v1. Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
Co-authored-by: epugh <22395+epugh@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
This PR adds Ref Guide documentation for Solr’s V2 update endpoints and (in the same change set) migrates the V2 /update implementation to a JAX-RS resource, including URI normalization to support the /c/ collection shorthand in Jersey routing.
Changes:
- Added a new Ref Guide page documenting V2 update endpoints and their behavior vs V1 update handlers.
- Updated indexing guide navigation to include and cross-reference the new V2 update documentation.
- Switched V2 update handling to a Jersey resource + added
/c/→/collections/URI normalization, along with updated tests and a new OpenAPI endpoint interface.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-v2-apis.adoc | New V2 update API documentation and V1↔V2 comparison. |
| solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-update-handlers.adoc | Cross-reference note + page-children update for new V2 page. |
| solr/solr-ref-guide/modules/indexing-guide/indexing-nav.adoc | Adds the new V2 page to the indexing sidebar nav. |
| solr/core/src/java/org/apache/solr/jersey/container/ContainerRequestUtils.java | Normalizes /c/ collection shorthand for Jersey path matching. |
| solr/core/src/java/org/apache/solr/handler/admin/api/UpdateAPI.java | New Jersey-based V2 update resource delegating to UpdateRequestHandler. |
| solr/core/src/java/org/apache/solr/handler/V2UpdateRequestHandler.java | Registers UpdateAPI as a Jersey resource and provides config injection. |
| solr/api/src/java/org/apache/solr/client/api/endpoint/UpdateApi.java | New OpenAPI/JAX-RS endpoint interface for v2 update paths. |
| solr/core/src/test/org/apache/solr/handler/V2UpdateAPIMappingTest.java | Removes old unit test for v2→v1 update path rewriting. |
| solr/core/src/test/org/apache/solr/handler.admin.api/UpdateAPITest.java | Adds integration tests covering V2 update endpoints. |
Comments suppressed due to low confidence (1)
solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-v2-apis.adoc:136
- Capitalization of “Javabin” here (and in the table / comparison section) is inconsistent with the rest of the ref guide, which uses “JavaBin”. Please standardize on “JavaBin” (while keeping the MIME type
application/javabinas-is).
== Javabin Document Indexing
The v2 `/update/bin` endpoint accepts documents in Javabin format, which is the native binary format used by SolrJ.
This endpoint is primarily intended for use by SolrJ clients.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
…-v2-apis.adoc Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
I hit an issue trying to do atomic update (JSON format) using v2 I'm leaning towards making the base
Example: curl -X POST 'http://localhost:8983/api/collections/mycollection/update?commit=true' \
-H 'Content-Type: application/vnd.solr.atomic+json' \
--data-binary '{"id": "mydoc", "price": {"set": 99}}'Not entirely sure whether atomic-syntax should be supported in normal |
I think with the V2 we shoudn't be constrained to V1 ideas.. I would extend that to the syntax we use in the payload... If there is a better way of structuring the JSON (or other payloads being sent) then we should do it. Now is the time to make a big change to our indexing patterns. Having said that, this PR ended up starting to be a big job, so that is why it's DRAFT on hold. But I would love any improvements you make to this PR! |
That's a good point, in V2 we can also change the atomic update contract to make it NOT ambigoous. Maybe there is a genuinely better way, maybe something refencing a field with jsonPath and the operation with some operation object? |
|
I did #4910 to test the ND-JSON idea. No atomic support, keep it simple. |
|
@janhoy I am going to address your feedback, and try to do them as cohesive commits, that way, if we want to pull any of them into brand NEW PR's so that this current PR can be mergable, we can. I know I struggle with scope creep a lot. Especially wihtout a good sense of "can I record "and this doesn't work"" and still make this a legit migration. Also, if when you see my next steps, you think "Lets break this up into X PR's" we can... If we want the js changes for example to be in their own PR. |
I dealt with this in ac83841 |
Love it! Thanks for thinking about it. |
…gh/solr into copilot/migrate-update-api-to-jax-rs
…ong typed responses. We may need to think about how update model objects have some sort of "escape" for when random third party Update Processors ADD to the repsonse. Rihgt now in this PR, we actually add strong typing.... Which may be fine, but what if we have processors dynamically loaded?
…out everything but metrics Committing as single chunk for furthur reveiw and feedback.
I'd say yes to this. When we approach completion, ask LLM to extract all frontend edits into its own branch/PR, stacked on top of this one, and commit separately. That said, I do appreciate using UI changes as a test bench for actually testing the generated JS client and vetting the API changes, that is how it should be done. |
in the vein, we could also pull out the use of techproducts in the examples into their own PR as well... Or you give a +1 and we merge this ;-) |
|
@epugh I'm going to push a commit bringing this PR up to date with main, so we can continue working on it. I will likely merge #4910 first since that is ready, but the conflict is not that complex. Also, there are 10 unresolved review comments in this PR, do you want to close the ones that are truly resolved? |
# Conflicts: # solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-update-handlers.adoc # solr/solr-ref-guide/modules/indexing-guide/pages/partial-document-updates.adoc # solr/solr-ref-guide/modules/indexing-guide/pages/transforming-and-indexing-custom-json.adoc # solr/webapp/web/js/angular/controllers/core-overview.js # solr/webapp/web/js/angular/controllers/cores.js # solr/webapp/web/js/angular/services.js
…ateTool The generated SolrJ request gained a contentType argument on this branch, and bin/solr create started using it on main (SOLR-18320).
…entions
{collectionName} placeholders, quoted URLs, --data-binary for update payloads,
and one command per line, as standardized on main by SOLR-18460, SOLR-18495
and SOLR-18500.
… pass the content type
|
🤖 Claude Fable 5 merged Conflicts resolved in the merge commit
Semantic conflicts, 8afa6bd and the commit after it: the Curl conventions, b98bc2f: swept the three pages above to main's current style: Validated locally with |
|
Automated PR readiness judgements (LLM-generated; may be wrong; not updated on later pushes).
|
janhoy
left a comment
There was a problem hiding this comment.
Quick browse through all files...
| throws SolrServerException, IOException { | ||
| try (final var stream = new ByteBufferInputStream(buffer)) { | ||
| final var uploadReq = new FileStoreApi.UploadFile(name, stream); | ||
| final var uploadReq = new FileStoreApi.UploadFile(name, stream, "application/octet-stream"); |
There was a problem hiding this comment.
Use a constant in place of string?
| var uploadReq = | ||
| new ConfigsetsApi.UploadConfigSet( | ||
| confName, new ByteArrayInputStream(Utils.zipDirectory(confPath))); | ||
| confName, new ByteArrayInputStream(Utils.zipDirectory(confPath)), "application/zip"); |
There was a problem hiding this comment.
Constant instead of string? Either from Jetty or from JDK
| // Create and execute the upload request using generated client | ||
| final var uploadRequest = | ||
| new ConfigsetsApi.UploadConfigSet(configSetName + suffix, fileBytes); | ||
| new ConfigsetsApi.UploadConfigSet(configSetName + suffix, fileBytes, "application/zip"); |
| final var uploadReq = new FileStoreApi.UploadFile(name, new ByteBufferInputStream(buffer)); | ||
| final var uploadReq = | ||
| new FileStoreApi.UploadFile( | ||
| name, new ByteBufferInputStream(buffer), "application/octet-stream"); |
| Increments or decrements a numeric field's value by a specific amount, specified as a single integer or float. | ||
| Positive amounts increment the field's value, and negative decrement. | ||
|
|
||
| NOTE: Atomic update syntax is supported exclusively on the `/update` endpoint. |
There was a problem hiding this comment.
I don't remember why this was. And is it precise to say "exclusively on the /update endpoint", when the /update endpoint now is a dispatcher to various sub handlers, which behave quite differently. It is only the json one with Content-Type: application/json that handles atomic update???
| [source,bash] | ||
| ---- | ||
| curl 'http://localhost:8983/api/collections/techproducts/update/json/docs'\ | ||
| curl 'http://localhost:8983/api/collections/techproducts/update/json'\ |
There was a problem hiding this comment.
It's a pity that v2 paths changelike this between v1 and v2 but I guess we considered all alternatives...
https://issues.apache.org/jira/browse/SOLR-18457
Summary
Migrate the V2 update APIs to JAX-RS while preserving the legacy update handler's indexing behavior. The new API contract exposes the supported update formats, query parameters, request bodies, and typed versioned responses.
API changes
UpdateApicontract and JerseyUpdateAPIimplementation./api/collections/{collection}/update/jsonfor document-only JSON indexing/api/collections/{collection}/update/xmlfor XML updates/api/collections/{collection}/update/csvfor CSV updates/api/collections/{collection}/update/javabinfor Javabin updatescommit,commitWithin,overwrite,softCommit, andversions.Content-Typeheader.adds,deletes, anddeleteByQueryversion entries./c/{collection}alias when routing requests through JAX-RS.The implementation delegates update processing to the existing
UpdateRequestHandler, so V1 and V2 continue to share the same loaders, update processors, routing, and commit behavior. The generic/updateendpoint accepts JSON update commands; the/update/jsonpath is the document-only JSON convenience endpoint.Documentation and Admin UI
indexing-with-update-handlers.adoc, using V1/V2 examples for JSON, XML, CSV, Javabin, versioned responses, and common update parameters.versions=truebehavior.Testing
UpdateAPITest, an integration test usingSolrJettyTestRule.