Skip to content

fix(indexing): one blank-input rule for every document format - #105

Closed
adityamparikh wants to merge 2 commits into
apache:mainfrom
adityamparikh:fix/document-creator-null-validation
Closed

adityamparikh wants to merge 2 commits into
apache:mainfrom
adityamparikh:fix/document-creator-null-validation

Conversation

@adityamparikh

@adityamparikh adityamparikh commented Apr 24, 2026 •

Copy link
Copy Markdown
Contributor

Problem

Four formats, three different rules for blank input, in two different layers:

Format Where the check lives on main What it does
JSON JsonDocumentCreator.create isBlank() → "JSON input cannot be empty"
CSV CsvDocumentCreator.create isBlank() → "CSV input cannot be empty"
XML IndexingDocumentCreator (orchestrator), creator has none null || trim().isEmpty() → "XML input cannot be null or empty"
Markdown orchestrator and creator orchestrator throws; creator silently returns List.of()

So new XmlDocumentCreator().create("") fails with a parser error, new MarkdownDocumentCreator().create(" ") returns an empty list, and the interface javadoc promised three mutually exclusive contracts that no implementation honoured.

Change

  • One SolrDocumentCreator.requireContent(content, format) helper, blank-only, message "<FORMAT> input cannot be empty". Every creator calls it first, so the contract holds for direct callers and through the orchestrator alike; the orchestrator's XML/Markdown checks are deleted rather than moved.
  • No null checks: the creators are @NullMarked, so a null argument is a caller's contract violation, and the only place a runtime null can enter is the reflective @McpTool boundary (fix: validate collection name consistently across all MCP tool methods #108 guards collection there). A client omitting the xml or markdown argument now gets the same NPE-derived tool error JSON and CSV already produced on main, until MCP SDK 2.0 input validation (feat: upgrade to Spring Boot 4.1.1 and Spring AI 2.0.1 #23) rejects missing required arguments before dispatch.
  • Interface and MarkdownDocumentCreator javadoc describe the one contract that now exists. No == null anywhere in the package.

Behavior changes to note: MarkdownDocumentCreator.create("") returned an empty list and now throws, and the XML/Markdown messages drop the "or null" wording.

Verification

DocumentCreatorBlankInputTest covers 4 formats × empty/whitespace directly against each creator; the existing XML and Markdown expectations move to the new message. ./gradlew build on Java 25: 410 tests, 0 failures.

🤖 Generated with Claude Code

@adityamparikh
adityamparikh force-pushed the fix/document-creator-null-validation branch from 51c5b8d to ac5e90d Compare May 2, 2026 17:04
@adityamparikh
adityamparikh force-pushed the fix/document-creator-null-validation branch from ac5e90d to a94d1f3 Compare August 18, 2026 21:25
@adityamparikh adityamparikh changed the title fix: add null/empty validation to JSON and CSV document creators fix(indexing): reject blank document input consistently across formats Aug 18, 2026
@adityamparikh
adityamparikh force-pushed the fix/document-creator-null-validation branch 2 times, most recently from a46d9b1 to 9fc28df Compare August 19, 2026 11:58
The four creators disagreed on where and how blank input was rejected: JSON
and CSV checked isBlank() in the creator, XML was checked only by the
orchestrator (the creator itself failed with a parse error), and Markdown was
checked in both places with different outcomes (orchestrator threw, creator
returned an empty list). The messages differed too, and the interface javadoc
promised three contracts none of them honoured.

One SolrDocumentCreator.requireContent(content, format) helper now runs first
in every create(); the orchestrator's two XML/Markdown checks are deleted. The
helper checks blankness only. The creators are @NullMarked, so a null argument
is a caller's contract violation rather than an input to validate; the null
branches main still carried are removed along with the XML null test that
pinned them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wh7SJkZhL1uuK7pYc3SLk8
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
@adityamparikh adityamparikh changed the title fix(indexing): reject blank document input consistently across formats fix(indexing): one blank-input rule for every document format Sep 11, 2026
@adityamparikh
adityamparikh force-pushed the fix/document-creator-null-validation branch from 9fc28df to 0851b26 Compare September 11, 2026 15:34
The create() javadoc still promised an empty list for blank input, which this
change removes. The two parameterized tests differed only in the input
literal, so they are one test over creators x blank inputs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01CiUHyyXLTo9ATdgg8eRFZJ
Signed-off-by: Aditya Parikh <aditya.m.parikh@gmail.com>
@adityamparikh

Copy link
Copy Markdown
Contributor Author

Closing as superseded.

This PR consolidates four scattered blank-input checks into one
SolrDocumentCreator.requireContent(content, format) helper. Three things have
since overtaken it.

#205 deletes half the call sites. It removes CsvDocumentCreator,
XmlDocumentCreator, XmlIndexingTest and the orchestrator's XML path, because
Solr's own /update handlers parse CSV and update XML. That is 3 of the 9 files
here deleted outright, plus one hunk of a fourth. What remains is JSON and
Markdown — two call sites, each a one-line if (x.isBlank()) throw. A static
helper on the interface, parameterised by a format-name string, is indirection
at that size rather than consolidation.

#202 and #207 rewrite the two survivors. #202 reworks JsonDocumentCreator
(+66/-28) and #207 reworks MarkdownDocumentCreator.create (+165/-50), so both
files this PR edits are being rebuilt by branches already in flight.

The signature no longer covers the shape. #202 adds
JsonDocumentCreator.create(List<Map<String, Object>>), whose emptiness check is
documents == null || documents.isEmpty() — not a String, so
requireContent(String, String) cannot serve it. The one duplication worth
fixing is the "JSON input cannot be empty" literal appearing in two methods of
that class after #202; that belongs in #202 as a named constant, not here.

No behaviour is lost by closing. Blank input is still rejected on every
format: IndexingDocumentCreator throws "Markdown input cannot be null or empty" on main today and #207 keeps that guard, and the JSON/CSV/XML creators
keep their own checks. This PR was a refactor, not a fix.

Separately, its own rationale — "the creators are @NullMarked, so a null
argument is a caller's contract violation, not an input to validate" — is being
applied repo-wide rather than in this one package, alongside making
@McpToolParam/@McpArg required explicit and dropping the null checks that
become dead as a result. Landing this now would adopt the narrower earlier
framing.

Thanks — the blank-input inconsistency it identified was real, and the repo-wide
version of the fix carries it forward.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant