Building Custom Reports with DynamicJasper — Step‑by‑StepDynamicJasper is a powerful library that simplifies building JasperReports reports programmatically in Java. Instead of designing complex .jrxml files by hand, DynamicJasper provides a fluent API to create columns, styles, groups, and layouts at runtime. This guide walks through creating a robust, production-ready PDF report with DynamicJasper, covering setup, basic report creation, styling, grouping, subreports, exporting, and common tips for performance and maintenance.
What you’ll build
A sales summary PDF showing:
- Report title and parameters (date range, region)
- Column-based details (date, order ID, customer, product, quantity, price, total)
- Grouping by customer with group totals
- A summary footer with grand totals
- Conditional styling (highlight large totals)
- Export to PDF
1. Setup and dependencies
Add Maven dependencies for DynamicJasper and JasperReports. Example (pom.xml):
<dependencies> <dependency> <groupId>ar.com.fdvs</groupId> <artifactId>DynamicJasper</artifactId> <version>5.1.0</version> </dependency> <dependency> <groupId>net.sf.jasperreports</groupId> <artifactId>jasperreports</artifactId> <version>6.20.0</version> </dependency> <!-- optional: PDF font support --> <dependency> <groupId>com.lowagie</groupId> <artifactId>itext</artifactId> <version>2.1.7</version> </dependency> </dependencies>
If you use Gradle, add equivalent artifacts. Ensure the JasperReports version is compatible with your DynamicJasper release.
2. Data model and sample data
Create a simple data class for sales rows:
public class Sale { private Date date; private String orderId; private String customer; private String product; private int quantity; private BigDecimal price; // constructors, getters, setters public BigDecimal getTotal() { return price.multiply(new BigDecimal(quantity)); } }
Prepare a List
3. Basic report with DynamicJasper
DynamicJasper uses FastReportBuilder and DynamicReport. Example creating columns and building the report:
FastReportBuilder drb = new FastReportBuilder(); AbstractColumn dateCol = ColumnBuilder.getNew() .setColumnProperty("date", Date.class.getName()) .setTitle("Date") .setWidth(80) .build(); AbstractColumn orderCol = ColumnBuilder.getNew() .setColumnProperty("orderId", String.class.getName()) .setTitle("Order ID") .setWidth(80) .build(); AbstractColumn customerCol = ColumnBuilder.getNew() .setColumnProperty("customer", String.class.getName()) .setTitle("Customer") .setWidth(120) .build(); // numeric columns AbstractColumn qtyCol = ColumnBuilder.getNew() .setColumnProperty("quantity", Integer.class.getName()) .setTitle("Quantity") .setWidth(50) .build(); AbstractColumn priceCol = ColumnBuilder.getNew() .setColumnProperty("price", BigDecimal.class.getName()) .setTitle("Price") .setPattern("$ 0.00") .setWidth(70) .build(); AbstractColumn totalCol = ColumnBuilder.getNew() .setColumnProperty("total", BigDecimal.class.getName()) .setTitle("Total") .setPattern("$ 0.00") .setWidth(80) .build(); drb.addColumn(dateCol) .addColumn(orderCol) .addColumn(customerCol) .addColumn(qtyCol) .addColumn(priceCol) .addColumn(totalCol) .setTitle("Sales Report") .setSubtitle("Generated with DynamicJasper") .setUseFullPageWidth(true); DynamicReport dr = drb.build();
Compile and fill the report:
JRDataSource ds = new JRBeanCollectionDataSource(salesList); JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), ds); JasperExportManager.exportReportToPdfFile(jp, "sales-report.pdf");
4. Styling: fonts, colors, conditional styles
Define styles to reuse across columns and groups:
Style titleStyle = new Style(); titleStyle.setFont(Font.getFont(Font.MEDIUM_BOLD)); titleStyle.setHorizontalAlign(HorizontalAlign.CENTER); titleStyle.setBackgroundColor(Color.LIGHT_GRAY); Style normalStyle = new Style(); normalStyle.setFont(Font.getFont(Font.ARIAL_SMALL));
Apply a style to a column:
dateCol.setStyle(normalStyle); totalCol.setStyle(normalStyle);
Conditional styling example — highlight totals over $1000:
Condition highValueCond = new Condition() { public boolean evaluate(Map fields, Map variables, Map parameters) { BigDecimal total = (BigDecimal) fields.get("total"); return total.compareTo(new BigDecimal("1000")) > 0; } }; Style highStyle = new Style(); highStyle.setTextColor(Color.RED); ConditionalStyle cs = new ConditionalStyle(highValueCond, highStyle); totalCol.addConditionalStyle(cs);
5. Grouping and subtotals
Group by customer and show subtotal for each group:
GroupBuilder gb = new GroupBuilder(); gb.setCriteriaColumn((PropertyColumn) customerCol); DJGroup customerGroup = gb.build(); drb.addGroup(customerGroup); // add subtotal variable drb.addGlobalFooterVariable(totalCol, DJCalculation.SUM, new SimpleExpression() {});
To show group footer totals:
customerGroup.setFooterVariables(new DJGroupVariable[]{ new DJGroupVariable(totalCol, DJCalculation.SUM) });
Adjust group header/footer styles and include labels like “Subtotal”.
6. Parameters and title customization
Add parameters for date range and region:
drb.addParameter("REPORT_TITLE", String.class); drb.setTitle("Sales Report for " + "$P{REPORT_TITLE}");
When filling:
Map<String,Object> params = new HashMap<>(); params.put("REPORT_TITLE", "East Region — Jan 2025"); JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), ds, params);
You can also add images (company logo) to the title band using ClassicLayoutManager features.
7. Subreports and complex layouts
DynamicJasper supports embedding subreports. Typical use: a detail report for order line items inside a main report of orders. Build subreport as a DynamicReport and include it as a column with a subreport expression or use JRSubreport in a custom template. For complex needs, creating a small .jrxml for the subreport and filling it programmatically can be simpler.
8. Pagination, page footer, and export options
Add page footer with page numbers:
drb.setPageFooter("Page: " + Page.PAGE_NUMBER + " of " + Page.TOTAL_PAGES);
For export options:
- PDF: JasperExportManager.exportReportToPdfFile(…)
- XLS/XLSX: JRXlsxExporter or JExcelApiExporter with exporter parameters
- HTML: JasperExportManager.exportReportToHtmlFile(…)
When exporting to Excel, set .setUseFullPageWidth(false) and avoid complex styles for better compatibility.
9. Performance tips
- Use JRBeanCollectionDataSource for small-to-medium datasets; use a JDBC connection + JasperReports built-in pagination for very large datasets.
- Limit complex expressions and avoid heavy use of conditional styles on huge row counts.
- Cache styles and re-use AbstractColumn objects where possible.
- For frequent report generation, compile and reuse templates or pre-build DynamicReport instances.
10. Testing and deployment
- Unit test report generation by producing a JasperPrint and verifying pages and key fields.
- Run performance/load tests with representative dataset sizes.
- In web apps, generate reports asynchronously and stream PDFs to users to avoid blocking threads.
Example: Complete working snippet
FastReportBuilder drb = new FastReportBuilder(); // build columns (dateCol, orderCol, customerCol, qtyCol, priceCol, totalCol) as above drb.addColumn(dateCol).addColumn(orderCol).addColumn(customerCol) .addColumn(qtyCol).addColumn(priceCol).addColumn(totalCol) .setTitle("Sales Report") .setUseFullPageWidth(true); DynamicReport dr = drb.build(); JRDataSource ds = new JRBeanCollectionDataSource(salesList); Map<String,Object> params = new HashMap<>(); params.put("REPORT_TITLE", "East Region — Jan 2025"); JasperPrint jp = DynamicJasperHelper.generateJasperPrint(dr, new ClassicLayoutManager(), ds, params); JasperExportManager.exportReportToPdfFile(jp, "sales-report.pdf");
Common pitfalls
- Mismatched property names between your bean and column definitions cause empty fields.
- Incompatible versions of DynamicJasper and JasperReports can lead to runtime errors.
- Overly complex styling can slow rendering or make Excel exports awkward.
Building custom reports with DynamicJasper lets you programmatically control layout and data while avoiding manual .jrxml maintenance. Start small (simple columns and a title), then add groups, styles, and parameters as needed.
Leave a Reply