Skip to content

SOLR-18457: Migrate V2 /update endpoints to using JAX-RS - #4177

Open
epugh wants to merge 41 commits into
apache:mainfrom
epugh:copilot/migrate-update-api-to-jax-rs
Open

epugh wants to merge 41 commits into
apache:mainfrom
epugh:copilot/migrate-update-api-to-jax-rs

Conversation

@epugh

@epugh epugh commented Mar 2, 2026

Copy link
Copy Markdown
Contributor

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

  • Add the JAX-RS UpdateApi contract and Jersey UpdateAPI implementation.
  • Support the generic V2 update endpoint with content-type driven format detection for JSON, XML, CSV, Javabin, and CBOR.
  • Add explicit V2 format paths:
    • /api/collections/{collection}/update/json for document-only JSON indexing
    • /api/collections/{collection}/update/xml for XML updates
    • /api/collections/{collection}/update/csv for CSV updates
    • /api/collections/{collection}/update/javabin for Javabin updates
  • Declare the supported query parameters in the OpenAPI contract, including commit, commitWithin, overwrite, softCommit, and versions.
  • Define the request bodies as streamed update content selected by the Content-Type header.
  • Return a strongly typed V2 response with typed adds, deletes, and deleteByQuery version entries.
  • Preserve response decoration and replication metadata while avoiding duplicate response headers.
  • Preserve the /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 /update endpoint accepts JSON update commands; the /update/json path is the document-only JSON convenience endpoint.

Documentation and Admin UI

  • Consolidate V1 and V2 update documentation in indexing-with-update-handlers.adoc, using V1/V2 examples for JSON, XML, CSV, Javabin, versioned responses, and common update parameters.
  • Update partial-document updates and custom JSON transformation examples for both APIs.
  • Document the typed V2 version response and the versions=true behavior.
  • Update the classic Admin UI Documents screen to submit JSON through the V2 update API and simplify its raw command flow.
  • Update the sample techproducts schema for nested documents and in-place updates.

Testing

  • Replace the old mapping test with UpdateAPITest, an integration test using SolrJettyTestRule.
  • Verify V1/V2 parity across supported update formats.
  • Verify custom JSON transformation and indexing through V2.
  • Verify assigned versions, typed versioned responses, XML response headers, and the generic update endpoint.
  • Run the reference guide build and the repository check excluding tests.

Copilot AI and others added 14 commits March 1, 2026 13:45
- 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>
@github-actions github-actions Bot added documentation Improvements or additions to documentation tests cat:api labels Mar 2, 2026
@epugh
epugh requested a review from Copilot March 2, 2026 18:15
@epugh epugh changed the title docs: Add indexing-with-v2-apis.adoc for V2 /update API endpoints Migrate V2 /update endpoints to using JAX-RS Mar 2, 2026

Copilot AI left a comment

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.

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/javabin as-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.

Comment thread solr/core/src/java/org/apache/solr/handler/admin/api/UpdateAPI.java
Comment thread solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-v2-apis.adoc Outdated
Comment thread solr/core/src/java/org/apache/solr/handler/admin/api/UpdateAPI.java Outdated
Comment thread solr/api/src/java/org/apache/solr/client/api/endpoint/UpdateApi.java Outdated
Comment thread solr/api/src/java/org/apache/solr/client/api/endpoint/UpdateApi.java Outdated
Comment thread solr/core/src/test/org/apache/solr/handler/admin/api/UpdateAPITest.java Outdated
epugh and others added 2 commits March 3, 2026 08:18
…-v2-apis.adoc

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

@epugh epugh left a comment

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.

This guy is tough!

Comment thread solr/core/src/test/org/apache/solr/handler/admin/api/UpdateAPITest.java Outdated
Comment thread solr/core/src/test/org/apache/solr/handler/admin/api/UpdateAPITest.java Outdated
Comment thread solr/core/src/java/org/apache/solr/handler/admin/api/UpdateAPI.java
Comment thread solr/core/src/java/org/apache/solr/handler/admin/api/UpdateAPI.java Outdated
Comment thread solr/solr-ref-guide/modules/indexing-guide/pages/indexing-with-v2-apis.adoc Outdated
@janhoy

janhoy commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

I hit an issue trying to do atomic update (JSON format) using v2 /update api. Does not work, and SOLR-11265 has been open for 9 years. Then I found this PR which looks promising in making some decent decisions for how the V2 JAX-RS update APIs should work.

I'm leaning towards making the base /api/collections/{collection}/update endpoint support multiple input formats (much like for v1). The HTTP standard supports this through Content-Type already. That way clients can be explicit in what they send and solr never need to doubt. We can also make extension content-types for solr e.g. for the "commands" JSON syntax:

Content-Type Behavior
application/json, text/csv, application/xml Straightforward, same as today's sub-paths
application/javabin or application/vnd.solr.javabin SolrJ's native binary format, already used internally, just exposed as a Content-Type on the main endpoint instead of only /update/bin
application/x-ndjson One JSON doc per line, for streaming bulk loads without a top-level array
application/vnd.solr.commands+json Top-level JSON parsed as the v1-style command envelope (add/delete/commit), restoring what this PR's table marks as unsupported in v2
application/vnd.solr.atomic+json Tells Solr that {"set": ...}, {"add": ...}, {"inc": ...} are atomic-update operators, not literal field structure — directly fixes SOLR-11265 by making intent explicit instead of guessing

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 application/json, I think it is problematic since we also need to support nested child docs and that gets ambigous. So an explicit application/vnd.solr.atomic+json would let Solr know what to expect. But then if you want atomic update of a deeply nested JSON -- well, what to do? Time to namespace the atomic qualifiers to avoid confusion, e.g. inc becomes _inc_, set becomes _set_ or similar.

@epugh

epugh commented Sep 12, 2026

Copy link
Copy Markdown
Contributor Author

Not entirely sure whether atomic-syntax should be supported in normal application/json, I think it is problematic since we also need to support nested child docs and that gets ambigous. So an explicit application/vnd.solr.atomic+json would let Solr know what to expect. But then if you want atomic update of a deeply nested JSON -- well, what to do? Time to namespace the atomic qualifiers to avoid confusion, e.g. inc becomes _inc_, set becomes _set_ or similar.

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!

@janhoy

janhoy commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

I think with the V2 we shoudn't be constrained to V1 ideas.

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?

@janhoy

janhoy commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

I did #4910 to test the ND-JSON idea. No atomic support, keep it simple.

Some magic here on how integrated, so added a comment.
@epugh

epugh commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

@janhoy just discoverd that in the V2 implemmetnation /update was changed to only be json.. Different from V1 where /update did the content-type negotiation. I think this might have been some subtle ju-jitsu to force us to making JSON our primary format. BUt we are in a multi format world, and heck, lets see some more CBOR or GRPC or Arrrow docs being indexed at /update!

@epugh

epugh commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

The Admin UI’s v1 update client code is now removed:

  • Removed the Update Angular service.
  • Removed stale Update injections from core controllers.
  • Removed all Update.postJson, postXml, and postCsv usage.
  • The Documents screen uses v2 for JSON, XML, CSV, and raw JSON commands.

The only remaining legacy update submission in the Admin UI is file upload through FileUpload, which posts multipart
data to:

/{core}/update

That path still uses the legacy update handler because the v2 API currently does not expose the multipart upload flow.

@epugh

epugh commented Sep 19, 2026

Copy link
Copy Markdown
Contributor Author

I fixed the weird UI where confirmation of an update showed up on the right below the fold, not on the right at the top...

public interface UpdateApi {

@POST
@Consumes({

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.

This is a big enhancement over the existing non JAX-RS appaoche, which required you to call /update/csv for cSV etc. Now we support content-types and you can access /update.

throws Exception;

@POST
@Path("/javabin")

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.

i debated leaving this on /update/bin to mimic more closing v1...

delete solrApi.ApiClient.instance.defaultHeaders["User-Agent"];
return new solrApi.SystemApi();
})
.factory('UpdateV2',

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.

Introducing this helped me find a bunch of small bugs and big gaps in the server side code!

@epugh

epugh commented Sep 20, 2026

Copy link
Copy Markdown
Contributor Author

@janhoy I've finsihed I think! I've rewritten the PR description to try and better capture all the work. I spent quite a few hours on the documentaiton today, and one thing I really was happy was moving it to using a real "techproducts" index, which mean I could test out that the docs worked by jsut using the provided curl examples! versus a more notional "if you had this, then this would work".... That did generate some chagnes to the techproducts configset. I also went ahead and move the Solr Admin Documents page to using the new V2 api! S

@epugh
epugh requested a review from gerlowskija September 20, 2026 01:10
@janhoy

janhoy commented Sep 21, 2026

Copy link
Copy Markdown
Contributor

Looks like I helped unleash some energy here. I like this new iteration and sticking to JAX-RS migration. Sure there is some scope creep with AdminUI etc, but tightly related and helping dog-food so warranted.

Have not reviewed in detail, but will try to have a deeper look.

PS: I'm maintaining a Solr training course and the other day I tried to move the hands-on Lab instructions for some indexing labs over to using V2, but it of course ended up with a mix of V1 and V2 commands since V2 lacks atomic update and "commands" support. But let's not de-rail this PR with such. Those two topics deserve some dev@ discussion first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants