Skip to content

WW-5733 fix(jasperreports7): stop closing the response stream before the report is written - #1923

Merged
lukaszlenart merged 1 commit into
mainfrom
WW-5733-stream-close
Sep 12, 2026
Merged

WW-5733 fix(jasperreports7): stop closing the response stream before the report is written#1923
lukaszlenart merged 1 commit into
mainfrom
WW-5733-stream-close

Conversation

@lukaszlenart

Copy link
Copy Markdown
Member

Fixes WW-5733

What

Every JasperReport7*ExporterProvider.createExporter obtained the servlet output stream in a try-with-resources block, so the stream was closed as soon as the method returned — before JasperReport7Result.exportReport called exporter.exportReport(). Tomcat commits the response on close() with the bytes written so far (none) and discards everything written afterwards, so every export from this plugin was an empty 200 with Content-Length: 0 — CSV, PDF, HTML, RTF, XML and XLSX alike, since 7.1.0. The unit tests never noticed because Spring's MockHttpServletResponse keeps accepting writes after close().

Reproduced on embedded Tomcat 10.1.34 with a servlet doing the same sequence (close in try-with-resources → write → flush): status=200 content-length=0 body=0 bytes; the same servlet without the close delivers the payload.

Fix

The six providers now hand the open stream to the exporter and leave it alone. JasperReport7Result still flushes after exporting; the container closes the stream at the end of the request, which is the normal servlet idiom. JasperReports' OutputStream-based exporter outputs do not close the stream either (toClose = false), so there is no double close. The 6.x plugin is unaffected — it buffers into a ByteArrayOutputStream and closes after writing.

Test

testExportWritesNothingAfterClosingTheResponseStream runs the result for all six formats against an HttpServletResponseWrapper whose ServletOutputStream rejects writes after close() — the container semantics the mock lacks. Before the fix it fails on the first format with IOException: Stream closed.

🤖 Generated with Claude Code

@lukaszlenart
lukaszlenart marked this pull request as ready for review September 12, 2026 10:09
…the report is written

Every exporter provider obtained the servlet output stream in a
try-with-resources block, so the stream was closed as soon as
createExporter returned, before JasperReport7Result called
exporter.exportReport(). Tomcat commits the response on close with the
bytes written so far, which is none, and drops everything written
afterwards: every export was an empty 200 with Content-Length: 0. The
tests did not notice because Spring's MockHttpServletResponse keeps
accepting writes after close.

The providers now hand the open stream to the exporter and leave it
alone; the result flushes after exporting and the container closes the
stream at the end of the request. A response wrapper that refuses
writes after close guards the ordering for all six formats.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

@lukaszlenart
lukaszlenart merged commit 9b8b0fa into main Sep 12, 2026
13 checks passed
@lukaszlenart
lukaszlenart deleted the WW-5733-stream-close branch September 12, 2026 12:29
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