Support multipage reports when the goal is invoked directly - #244
Support multipage reports when the goal is invoked directly#244slachiewicz wants to merge 1 commit into
Conversation
reportToSite() passed a null SinkFactory to generate(), so any report that creates sub-sinks for additional pages failed with an NPE as soon as its goal was run from the command line rather than through the site. The maven-plugin-report-plugin report is one such report. Provide the same MultiPageSinkFactory that Maven Site Plugin's ReportDocumentRenderer provides, collect the sub-sinks it hands out and merge each of them into the site next to the main document. The integration test for this was already written and disabled with a pointer to the issue, so it is simply enabled again.
There was a problem hiding this comment.
Pull request overview
This PR fixes a NullPointerException when invoking reporting goals directly for multipage reports by providing a SinkFactory during site rendering, aligning behavior with Maven Site Plugin so multipage reports work consistently in both direct-goal and site modes.
Changes:
- Provide a
MultiPageSinkFactorytogenerate(...)inreportToSite()and render any collected subpage sinks after the main page is merged into the site. - Add internal
MultiPageSubSink/MultiPageSinkFactoryhelpers to track subpage output locations and rendering contexts. - Re-enable and strengthen the existing IT (
use-as-direct-mojo) to verify both multipage outputs exist and contain expected content.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| src/main/java/org/apache/maven/reporting/AbstractMavenReport.java | Passes a sink factory for multipage sub-sinks during direct-goal site rendering and merges generated subpages into the site output. |
| src/it/use-as-direct-mojo/verify.groovy | Re-enables assertions for multipage output and validates rendered content. |
| src/it/use-as-direct-mojo/invoker.properties | Re-enables the multipage goal in the direct-mojo IT. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| String document = PathTool.getRelativeFilePath( | ||
| report.getReportOutputDirectory().getPath(), new File(outputDirectory, outputName).getPath()); | ||
| // Remove .html suffix since we know that we are in Site Renderer context | ||
| document = document.substring(0, document.lastIndexOf('.')); | ||
|
|
There was a problem hiding this comment.
The claim is right — lastIndexOf returns -1 for a name with no dot and substring(0, -1) throws.
I have left it, deliberately. That line is copied verbatim from MultiPageSinkFactory in maven-site-plugin's ReportDocumentRenderer, and the point of this PR is that a multipage report behaves the same whether its goal is invoked directly or through the site. Making only this copy lenient would mean a report using an extension-less name works standalone and throws under mvn site, which is a worse failure mode than both rejecting it consistently: it would only show up in one of the two paths.
The implied contract is that the name ends in .html — the site plugin's own comment on that line says "Remove .html suffix since we know that we are in Site Renderer context" — so an extension-less name is invalid input either way. Happy to fix it in both places in a follow-up if a maintainer wants the diagnostic improved; it should not be fixed in just one.
Fixes #217.
reportToSite()passednullas theSinkFactorytogenerate(Sink, SinkFactory, Locale), with a TODO saying multipage reports would fail with an NPE. They do:Only the site path was affected.
reportToMarkup(), taken whenoutput.formatis set, already builds a sink factory, which is whyuse-as-direct-mojo-markupexercises the multi-page mojo happily whileuse-as-direct-mojocould not.The change
Hand
generate()aMultiPageSinkFactorymirroring the one in Maven Site Plugin'sReportDocumentRenderer: eachcreateSink(File, String)builds aDocumentRenderingContextderived from the main one, wraps it in aSiteRendererSinkthat remembers where it belongs, and records it. After the main document is merged into the site, every collected sub-sink is merged the same way.Keeping the structure identical to
ReportDocumentRendereris deliberate, so the two stay easy to compare, and so a report behaves the same whether its goal is invoked directly or through the site.Test
The integration test for exactly this was already written and disabled with a pointer to the issue, in
src/it/use-as-direct-mojo. This PR enablesinvoker.goals.4 = custom-reporting:multi-pageagain and uncomments theverify.groovyassertions, extended to also check the rendered content rather than mere file existence.I confirmed it is a real regression guard: reverting only
AbstractMavenReportand rerunning the IT reproduces the reported failure.With the change,
mvn verifyis green over the full IT suite (6 passed), and the multipage goal logs both pages:I did not rebuild maven-plugin-report-plugin against this branch to re-verify the original report from the issue; the IT covers the same code path with the same API.