Skip to content

SOLR-18351: remove ContentStream from SolrJ's client write path - #4811

Open
serhiy-bzhezytskyy wants to merge 11 commits into
apache:mainfrom
serhiy-bzhezytskyy:SOLR-18351-contentstream-investigation
Open

SOLR-18351: remove ContentStream from SolrJ's client write path#4811
serhiy-bzhezytskyy wants to merge 11 commits into
apache:mainfrom
serhiy-bzhezytskyy:SOLR-18351-contentstream-investigation

Conversation

@serhiy-bzhezytskyy

@serhiy-bzhezytskyy serhiy-bzhezytskyy commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

https://issues.apache.org/jira/browse/SOLR-18351

Removes ContentStream from SolrJ entirely.

ContentStream/ContentStreamBase move to solr-core as org.apache.solr.util, un-deprecated -- they're the server's pull-side contract (SolrQueryRequest#getContentStreams), which ContentWriter (push) has no equivalent for. Not the old package name: that would have been the build's only package with classes in both jars, which renderJavadoc rejects.

Removed from SolrJ:

  • ContentStreamUpdateRequest -> ContentWriterUpdateRequest (addPart(name, ContentWriter) primitive, addFile/addContent conveniences). Multipart behavior unchanged.
  • ConfigSetAdminRequest.Upload.setUploadStream -> setUploadContent(ContentWriter)
  • ClientUtils.toContentStreams
  • CommandOperation.readCommands(Iterable<ContentStream>, ...) -> ApiBag; all three callers are solr-core handlers. The parse(Reader/InputStream) overloads stay.

Behavior change: the old FileStream silently gunzipped .gz files and guessed a missing content type; uploaded files no longer get either. Nothing in-repo relied on it, but it was public, so it's in the changelog.

AI-assisted (Claude Sonnet 5)

Adds MultipartContentWriter/NamedPart to RequestWriter so a request with
several named parts can go through getContentWriter() instead of the
deprecated getContentStreams() fallback -- HttpJettySolrClient builds a real
multipart/form-data body from it (verified end-to-end against a real Jetty
server); HttpJdkSolrClient keeps rejecting multipart, as before.

ContentStream itself stays: it's still the server-read-side contract
(SolrQueryRequest#getContentStreams, ~50 core files), which ContentWriter
has no equivalent for.
@serhiy-bzhezytskyy

serhiy-bzhezytskyy commented Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

@epugh does this need a changelog entry, or can you add no-changelog?

@dsmiley

dsmiley commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

Thanks!
I had hoped to be able to remove ContentStream from SolrJ, putting in solr-core.jar, but this approach keeps references to it from SolrJ. It's not a big deal though. WDYT?
I'm a little surprised to see this keeps multi-part upload in SolrJ. There is complexity in retaining that... I'm not sure it's worthwhile. WDYT?

@serhiy-bzhezytskyy

Copy link
Copy Markdown
Contributor Author

On ContentStream's location: you already answered this yourself on SOLR-18116 back in Feb -- "the server needs to pull the data from the client... All servers have a pull model." That's still the blocker, plus moving the class into solr-core would mean SolrJ's own public write API (addContentStream, setUploadStream, toContentStreams) takes a type from a module that depends on SolrJ, not the reverse. Mikhail hit the same wall trying this in SOLR-11657 (2019) -- EmbeddedSolrServer, the HTTP clients enumerating streams.

On multi-part: not theoretical -- ManifoldCF hit a production blocker in 2018 (SOLR-12798) when params exceeded URL limits and multipart was the fix; an independent user (Christian Beikov) hit the same wall in 2020. That's exactly what SOLR-12843 added multipart support for in the first place -- this PR just carries it forward through the ContentStream->ContentWriter migration. Dropping it would regress a real, previously-reported problem, not just an unused code path.

@dsmiley

dsmiley commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

My proposal to move ContentStream from SolrJ to Solr-core would imply a removal of all usages of it in SolrJ. It would certainly not imply a dependency on solr-core; that's unacceptable. Looking at the examples you listed, it means ContentStreamUpdateRequest would disappear entirely. org.apache.solr.client.solrj.request.ConfigSetAdminRequest.Upload#setUploadStream would be eliminated.

Move ContentStream/ContentStreamBase to solr-core (same package, so
server-side imports are unchanged) and un-deprecate them -- they are the
server's pull-side contract. SolrJ now writes only via ContentWriter.

ContentStreamUpdateRequest is replaced by ContentWriterUpdateRequest,
ConfigSetAdminRequest.Upload.setUploadStream by setUploadContent,
ClientUtils.toContentStreams is gone, and CommandOperation's
ContentStream-reading overloads move to ApiBag.
…ckage

Keeping the old org.apache.solr.common.util name would have made it the
build's only package with classes in both the solrj and solr-core jars,
which renderJavadoc flagged.
@serhiy-bzhezytskyy

Copy link
Copy Markdown
Contributor Author

Done -- ContentStream is out of SolrJ entirely: ContentStreamUpdateRequest and setUploadStream gone, CommandOperation's ContentStream overloads moved to ApiBag, the class itself now in solr-core, un-deprecated. Put it in org.apache.solr.util rather than keeping org.apache.solr.common.util -- the old name would have been the build's only package with classes in both jars, which renderJavadoc rejects.

@dsmiley

dsmiley commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

I only wanted to discuss your opinion on the viability of my proposal (at this time). Moving ContentStream is definitely out-of-scope of SOLR-18351, however actually doing was useful as it forces a thorough examination of what needs to be done. I could imagine you restoring any non-deprecated thing you removed from solrj but then add the deprecation marker. And then revert anything outside of SolrJ (assuming changes outside of SolrJ are related to a move we undo). A changelog would then mention added SolrJ APIs to replace what's deprecated.

@dsmiley

dsmiley commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

BTW a motivator of why I deprecated ContentStream is that it felt redundant with ContentWriter in SolrJ, and it added complexity to support both.

@serhiy-bzhezytskyy

Copy link
Copy Markdown
Contributor Author

it would be hard to estimate complexity and final result without these exercises. just to be aligned - what is action item here?

…eam-investigation

# Conflicts:
#	solr/core/src/java/org/apache/solr/util/ContentStream.java
#	solr/solrj/src/java/org/apache/solr/client/solrj/SolrRequest.java
#	solr/solrj/src/java/org/apache/solr/client/solrj/WrappedSolrRequest.java
#	solr/solrj/src/java/org/apache/solr/client/solrj/request/RequestWriter.java
@dsmiley

dsmiley commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

I suggest reverting the move of ContentStream, however retain the changes within SolrJ that support that future end-state (that you have already done). Thus remove things and add things accordingly (as you have already done -- retain). The result is that SolrJ doesn't use ContentStream at all. A future PR could move for 11.x. This PR is for 10.1 so removed a few ~osbscure things that weren't deprecated... albeit those things used the deprecated ContentStream so I'm comfortable with the change in 10.1. The changelog should definitely explain.

Per review: SolrJ stops using ContentStream, but the class stays where it
is; moving it out of SolrJ is left to a later release.
@serhiy-bzhezytskyy

Copy link
Copy Markdown
Contributor Author

Hope I understood you correctly. ContentStream is back in org.apache.solr.common.util, still deprecated. Retained the SolrJ-side changes, so SolrJ itself no longer uses it anywhere. Changelog updated to say the move is left for a later release.

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.

2 participants