← All writing

Sep 7, 2026 · 5 min read · Reporting

Maintainable Reports with JasperReports Subreports

A single 40-band Jasper template that does everything becomes unmaintainable fast. Subreports let you compose reports from small, reusable pieces — here's how to wire them up without the usual headaches.

Why subreports?

A subreport is just a compiled report embedded inside another. Reach for them when you need to:

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:

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

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.

Building reporting-heavy systems? Let's compare notes.

Get in Touch