I've built a small stress-test project, testing report generation with HTML elements in concurrent environment.
What it does, it compiles a simple report with non-trivial HTML markup witin text elements, runs it in concurrent environment and compares the rendering results with a golden rendering reference. The reference might be not proper and not the best rendering result representation, however the example show the result being inconsistent even on small amount of tasks (run without arguments couple of times):
JasperReports stress-test results
Requested runs: 40
Available processors: 20
Executor threads: 40
HTMLEditorKit warm-up: disabled
JEditorPane warm-up: disabled
Legacy HTML processor: disabled
EDT HTML rendering: disabled
Successful runs: 38
Verification mismatches: 2
Errored runs: 0
Elapsed: 0.518 s
Throughput: 77.2 fills/s
The underlying reason is that HtmlEditorKitMarkupProcessor creates Java Swing objects concurrently and Java Swing concurrency contract never actually allowed that.
There are potential workarounds shown in the project:
--edt-rendering - delegate rendering to Swing Event Dispatch Thread. This flag makes the test reliably pass (at least on my machine)
It also has an option to enable legacy rendering with JEditorPane: --legacy-jeditor-pane-processor, which also does not show good results.
There are also some Swing warm up hacks --html-editor-kit-warmup and --jeditor-pane-warmup which make the test work without resorting to EDT rendering. They are AI-crafted, show good results, but I cannot fully trust them and they might now survive Swing update.
Clearly that affects concurrent report generation with Jasper and potentially can affect single report generation with subreports (I know Jasper can delegate subreport rendering to a thread and does so by default, but I don't know how to make it actually run concurrently).
Potential fixes from jasperreports side could be:
- Do nothing and honestly admin that report generation cannot be run concurrently (bad option?).
- Apply EDT-delegation to all HTML (and probably RTF) rendering. This would be a proper Swing usage, but may create a performance bottleneck if we want report generation to be really concurrent.
- Rely on "warm ups". Can be better in terms of performance, but these warm ups rely on deep Swing internals and can be unreliable and hard to maintain
- Switch to some other machinery for HTML/RTF rendering. I tried building one with JSoup library, but apparently bare HTML parser is not enough: I had to build poor man's style semantics processor myself. More powerful tools seems like a worse choice than Java Swing rendering (yes, now I see why you went with it in the first place). Flying Saucer claimed to be unreliable under concurrent environment (yet the claim is 10 years old), CSSBox seems half dead.
I honestly don't know which solution is right (all of them have drawbacks), but I've gave you an example to think about.
Additional info:
JasperReports: 7.0.8
Java: OpenJDK 25
Java runtime build: 25+36-3489
JVM: OpenJDK 64-Bit Server VM 25+36-3489, mixed mode
Java vendor: Oracle Corporation
OS: Windows 11 Pro 25H2, AMD64, build 26200.8875
Runtime-visible logical processors: 20
I've built a small stress-test project, testing report generation with HTML elements in concurrent environment.
What it does, it compiles a simple report with non-trivial HTML markup witin text elements, runs it in concurrent environment and compares the rendering results with a golden rendering reference. The reference might be not proper and not the best rendering result representation, however the example show the result being inconsistent even on small amount of tasks (run without arguments couple of times):
The underlying reason is that
HtmlEditorKitMarkupProcessorcreates Java Swing objects concurrently and Java Swing concurrency contract never actually allowed that.There are potential workarounds shown in the project:
--edt-rendering- delegate rendering to Swing Event Dispatch Thread. This flag makes the test reliably pass (at least on my machine)It also has an option to enable legacy rendering with JEditorPane:
--legacy-jeditor-pane-processor, which also does not show good results.There are also some Swing warm up hacks
--html-editor-kit-warmupand--jeditor-pane-warmupwhich make the test work without resorting to EDT rendering. They are AI-crafted, show good results, but I cannot fully trust them and they might now survive Swing update.Clearly that affects concurrent report generation with Jasper and potentially can affect single report generation with subreports (I know Jasper can delegate subreport rendering to a thread and does so by default, but I don't know how to make it actually run concurrently).
Potential fixes from jasperreports side could be:
I honestly don't know which solution is right (all of them have drawbacks), but I've gave you an example to think about.
Additional info:
JasperReports: 7.0.8
Java: OpenJDK 25
Java runtime build: 25+36-3489
JVM: OpenJDK 64-Bit Server VM 25+36-3489, mixed mode
Java vendor: Oracle Corporation
OS: Windows 11 Pro 25H2, AMD64, build 26200.8875
Runtime-visible logical processors: 20