Repository navigation
jasper-modular 3.0.0 is the next release after 2.0.1. Version 2.1.0 was never published, so everything it contained ships here. This is a major release: subreport parameter names change, and templates are now checked against your classes at build time. See Migrating from 2.0.x before upgrading.
Highlights
- Repeating subreports from lists of modules. A
List<T>field, whereTis a@JasperSubreportmodule, renders one subreport instance per element. Every element brings its own compiled template, so one list can hold subclasses of a module with different templates. In 2.0.1 this was not supported. - Empty modules are skipped. A module whose
isEmpty()returnstrueis skipped entirely — no parameters, no blank space. Empty andnullelements are dropped from subreport lists. - Collections of simple values.
List<String>, numbers, dates and enums get a dataset with a single_THISfield — the element itself — and a generated component. Previously the processor turned JDK types into nonsense fields such asbytesorempty. - Templates are checked at build time. The build fails when a template still declares a generated parameter or dataset that no field produces, or declares a parameter with a class that differs from its field. The error message says what to rename or delete.
⚠️ Breaking changes
- Subreport parameter names come from the field. A field
itemsproducesitemsReportanditemsMapParameter; a list of modules in a fielditemsproducesitemsDataSourcewith the datasetitemsDataset. In 2.0.x the prefix was theprefixattribute or the module's simple class name. Rename the old parameters and their$P{...}references in your templates — the build lists which ones. prefixis removed from@JasperSubreport.- Bean collections default to
TABLE. A collection field without@JasperCollectionnow generates atablewith column headers instead of alist. Components already in your templates are not changed; add@JasperCollection(type = CollectionComponentType.LIST)to keep generating lists. SubreportModule.getOrder()andisStartNewPage()are removed. They never affected rendering; control order and page breaks in the template.- New compile errors. Besides the template check above, the build now fails when:
- a
@JasperModularReportclass does not extendModularReport, or a@JasperSubreportclass does not extendSubreportModule; - a class carries both annotations, or the annotation is placed on a record, enum or interface;
- two classes use the same
templatePath; - two fields resolve to the same subreport parameter name;
- a collection element is a record, or a collection of modules uses an element type without
@JasperSubreport.
- a
Improvements and fixes
- Inheritance. Templates are generated only for classes that carry the annotation themselves. A subclass without its own annotation renders with the template of its nearest annotated ancestor, and a field declared with a base module type renders each instance with that instance's own template.
- Template paths work with or without a leading
/and share one cache entry. The startup precompiler resolves paths with the same rule as the runtime and compiles each template once, even when subclasses inherit it. - Dataset fields follow JavaBeans rules. Names come from the accessors, and the field class comes from the getter chosen by JavaBeans priority. Interface element types get their fields from their getters. Static fields without an accessor are skipped.
- Clear warnings instead of silent gaps. A raw
List,List<?>or an element type without readable properties produces a warning that points at the field. If the processor cannot find an existing template, it now warns before generating a blank skeleton — it looks in the compiled-classes output first, then on its own classpath. - No blank space for empty collections. Generated
list/tablecomponents and subreport lists float and setremoveLineWhenBlank. - Runtime: synthetic fields (for example JaCoCo's
$jacocoData) no longer leak into the parameter map; wildcard element types are resolved the same way as in the processor; the template cache is cleared on every startup, sospring-boot-devtoolsrestarts pick up edited JRXML. Static fields are still passed as parameters by design — use@JasperIgnoreto exclude one. - Processor stability: type-variable fields no longer break generation.
Compatibility
- Java 17+.
- Spring Boot 3.3+ or 4.x for the starter (autoconfiguration and precompiler); the core does not depend on Spring.
- JasperReports 6.x or 7.x in
providedscope — bring your own engine version. Tested with 6.21.5 and 7.0.6. JRXML files are not interchangeable between 6.x and 7.x, so keep templates for the engine you run; the processor writes the dialect of the JasperReports version on its path.
Installation
<dependency>
<groupId>io.github.hhdevr</groupId>
<artifactId>jasper-modular-starter</artifactId>
<version>3.0.0</version>
</dependency>Add io.github.hhdevr:jasper-modular-processor:3.0.0 to annotationProcessorPaths together with your JasperReports version — see the README. A complete example lives in jasper-modular-sample.