Why subreports?
A subreport is just a compiled report embedded inside another. Reach for them when you need to:
- Repeat a detailed block per record (e.g. an invoice with its line items).
- Reuse the same component — a header, a signature block — across many reports.
- Break one enormous template into pieces different people can own.
Passing parameters down
The parent passes values to the child through <subreportParameter>.
Keep the parent's report parameters as the single source of truth and forward what the
child needs:
<subreport>
<reportElement x="0" y="0" width="555" height="80"/>
<subreportParameter name="INVOICE_ID">
<subreportParameterExpression>$F{id}</subreportParameterExpression>
</subreportParameter>
<subreportExpression>$P{ITEMS_SUBREPORT}</subreportExpression>
</subreport>
Give the subreport its own data
There are two common ways to feed a subreport:
- Pass a data source from the parent via
$P{REPORT_DATA_SOURCE}— best when the parent already has the data in memory. - Pass a connection and let the subreport run its own query — cleaner when each section maps to its own SQL.
Compile the child to a .jasper and pass it in as a parameter or a pre-loaded object:
JasperReport itemsSub = JasperCompileManager.compileReport("items.jrxml");
params.put("ITEMS_SUBREPORT", itemsSub);
Pitfalls I learned the hard way
- Compile every subreport. A stale
.jrxml/.jaspermismatch is the #1 cause of "why is it showing old data?". - Watch the width. A subreport wider than the parent band silently overflows or clips. Match widths deliberately.
- Set “Print When Detail Overflows” / stretch so a growing subreport pushes content down instead of overlapping.
- Cache compiled reports. Compiling on every request is expensive — compile once at startup and reuse.
Performance
Reports are read-heavy, so the same rule from query optimization applies: fetch only the columns you render, do aggregation in SQL, and avoid running a fresh query per row inside a subreport when a single joined query would do.
Treat a report like code: small composable pieces, compiled artifacts under version control, and data-fetching that respects the database.
✍️ This is a starter draft on my site — personalize it, add a screenshot of a real report, or a concrete before/after before sharing.