-
Notifications
You must be signed in to change notification settings - Fork 7
Jasper reports
Here you will learn how to create a Jasper report, include it into TG based application, produce a PDF file, and how to present it for printing or email it as an attachment.
To develop Jasper report for TG-based projects (Jaspersoft iReport Designer 4.7.1)[https://sourceforge.net/projects/ireport/files/iReport/iReport-4.7.1/] should be used.
There are two types of reports:
- simple report (all data is gathered from one or a few entities and is simply presented)
- more complex report; such a report will contain one or more sub-reports (in this case data usually is presented as lines, with header and grid on the background)
Often some sort of logo is presented in the report.
For example for the TG PSA project Fielden's logo is stored at the following location:
tgpsa\tgpsa\tgpsa-web-server\src\main\resources\report_templates\images\logo.png
Two templates were created for the TG PSA project: SimpleReportWithLogo.jrxml
and ReportWithSubreport.jrxml
to simplify the process of developing reports. These templates are located at tgpsa\tgpsa\tgpsa-web-server\src\main\resources\report_templates
.
Three report styles [1] are introduced: reportStyle
, reportBoldStyle
and reportStyleArialBlack
, which are used in both report and sub-report.
Style reportStyleArialBlack
is used for Report Title only.
Style reportBoldStyle
is used for labeling of data. The word Description in a report or column headers: Item No, Description, Amount in the sub-report are using this style.
Style reportStyle
is used for data fields.
To include logo into the report the report parameter imagePath [2] is introduced to provide location for all images. This parameter is used in the Image Expression of the image object to specify what picture would be shown.
To represent data in the report new Fields [3] should be added. The same is applicable to the sub-reports.
The field should be of type String
as all formatting would be done in TG. Names are case sensitive!
Better to use same rules as in TG when naming variables here and make sure when you provide real data in TG you are using the correct names.
Page Footer [4] contains some useful examples which are sometimes necessary when designing a report: today's date/time and page numbering.
A sub-report usually contains two sections: Column Header and Details.
It should contain the same Styles [1] for consistency with the main report. Please specify meaningful names for Report name [2], and Page size [3] should be the size of the area used by the sub-report in the report, this is especially important when you have a few sub-reports! The Job Pack for TTGAMS is good example where 5 sub-reports are presented one after the other.
Sub-report has to be compiled and as result SimpleSubreport.jasper will be created. This Jasper file has to be committed and released to the client. The TG-based application will be looking for this Jasper file for sub-reports as only the main report could be compiled at run time.
To generate the Jasper file simply press the Preview option in the designer.
Two additional parameters are introduced: subreport and subreportData [1].
Object Subreport [2] is added into the Details section, also some rectangles to represent a grid on the background.
Some properties of a sub-report object are very important.
For example Width and Height [2] should correspond to the Page size of the sub-report.
sub-report Expression and Data Source Expression [2] should point to our additional parameters subreport
and subreportData
.
Let's use the Tax Invoice report from the TG PSA project as an example.
InvoiceReport.jrxml
was designed (it contains sub-report InvoiceLinesSubreport.jrxml) by using the templates described above as a base during development.
The next step is to create a Java class that will collect all the necessary data, provide it to the Jasper report, and compile it into a PDF file.
InvoiceReport.java
was created in tgpsa-pojo-bl\src\main\java\fielden\project\reports\
.
This class has a public method reportAsPdf(final InvoiceHeader invoiceHeader, final IInvoiceLine coInvoiceLine)
, which does all necessary steps.
public byte[] reportAsPdf(final InvoiceHeader invoiceHeader, final IInvoiceLine coInvoiceLine) throws JRException {
// retrieve all necessary data using provided invoiceHeader
final List<Map<String, ?>> data = new ArrayList<>();
data.add(createInvoiceHeader(invoiceHeader));
// creating data source for lines sub report
final List<EntityAggregates> lines = aggregateLines(invoiceHeader, coInvoiceLine);
final JRRewindableDataSource jrsLines = new EntityAggregatesReportSource(lines.toArray(new EntityAggregates[] {}), subreportProps);
final JasperReport report = JasperCompileManager.compileReport(reportTemplatePath);
addPdfFontsToStyles(report.getStyles());
// filling report template with data and parameters
final JRMapCollectionDataSource dataSource = new JRMapCollectionDataSource(data);
final Map<String, Object> params = new HashMap<>();
params.put("imagePath", reportImagePath);
params.put("subReport", subreportTemplatePath);
params.put("subReportData", jrsLines);
final JasperPrint print = JasperFillManager.fillReport(report, params, dataSource);
// exporting to PDF file as byte array
final JRPdfExporter exporter = new JRPdfExporter();
exporter.setParameter(JRExporterParameter.CHARACTER_ENCODING, "UTF-8");
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
// will automatically also show "Print" dialog upon opening
exporter.setParameter(JRPdfExporterParameter.PDF_JAVASCRIPT, "this.print();");
exporter.exportReport();
return outputStream.toByteArray();
}
Method createInvoiceHeader(invoiceHeader)
retrieves all necessary data for the main report using the provided invoiceHeader
.
Method aggregateLines(invoiceHeader, coInvoiceLine)
retrieves all the necessary data for the sub-report, produces List<EntityAggregates>
that is transformed into the JRRewindableDataSource
.
After that the main report is compiled, three report styles are included, data is provided for additional parameters:
imagePath
, subReport
and subReportData
.
JasperFillManager and JRPdfExporter take care of the rest of the functionality: filling the report and producing output as a PDF file.
Usually an action has to be created to trigger the report creation and printing process.
In this particular case existing action InvoiceApprovalAction
was used and extended with printing functionality (as invoice approval triggers Tax Invoice print out by design).
Three additional properties mime
, fileName
and data
were added to the InvoiceApprovalAction
entity.
public class InvoiceApprovalAction extends AbstractFunctionalEntityWithCentreContext<String>
// the following 3 properties pertain to the creation of the PDF representation of the invoice
@IsProperty
@Readonly
@Title(value = "MIME", desc = "File MIME Type.")
private String mime; // application/pdf, application/vnd.ms-excel, text/plain, text/html
@IsProperty
@Title(value = "File Name", desc = "The name of file that Invoice report will produce. For eg. InvoiceNo_002161.pdf.")
private String fileName;
@IsProperty
@Title(value = "Data", desc = "Raw binary data that was produced by Jasper report and needs to be persisted.")
private byte[] data;
A value for property mime
is provided in the new_()
method:
@Override
public InvoiceApprovalAction new_() {
return super.new_().setMime("PDF");
}
A value for property fileName
is provided in the producer:
final String fileName = "InvoiceNo_" + invoiceHeader.getKey() + ".pdf";
entity.beginInitialising();
entity.setFileName(fileName);
entity.endInitialising();
Property data
will contain the outcome from Jasper report generation, which is done in the save()
method:
// let's generate report as PDF file with fileName
try {
final byte[] reportOutputStream = new InvoiceReport().reportAsPdf(invoiceHeader, co(InvoiceLine.class));
entity.setData(reportOutputStream);
} catch (final JRException e) {
throw Result.asRuntime(e);
}
Now to present this generated PDF file to the user for review and printing, the post action for this InvoiceApprovalAction
should be modified and new FileSaverPostAction()
used.
final EntityActionConfig approvalAction = action(InvoiceApprovalAction.class)
.withContext(context().withSelectionCrit().withSelectedEntities().build())
.postActionSuccess(new FileSaverPostAction())
.icon("icons:check-circle")
.withStyle(CUSTOM_ACTION_COLOUR)
.shortDesc("Approve selected Invoice")
.longDesc("Approve selected Invoice")
.build();
Jasper-related dependencies have to be included into pom files.
All fonts used during report development should be included in tgpsa-dao\pom.xml
for testing purposes and tgpsa\tgpsa-web-server\pom.xml
for production release.
<dependency>
<groupId>fielden</groupId>
<artifactId>jasper-fonts</artifactId>
<classifier>ariblk</classifier>
<version>1.0</version>
</dependency>
<dependency>
<groupId>fielden</groupId>
<artifactId>jasper-fonts</artifactId>
<classifier>calibri</classifier>
<version>1.0</version>
</dependency>
<dependency>
<groupId>fielden</groupId>
<artifactId>jasper-fonts</artifactId>
<classifier>times</classifier>
<version>1.0</version>
</dependency>
<dependency>
<groupId>fielden</groupId>
<artifactId>jasper-fonts</artifactId>
<classifier>wingding</classifier>
<version>1.0</version>
</dependency>
tgpsa\tgpsa-web-server\pom.xml
should also contain instructions on coping of Jasper reports.
<execution>
<id>copy-jasper-reports</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<encoding>UTF-8</encoding>
<outputDirectory>${staging.dir}/deployment/report_templates</outputDirectory>
<resources>
<resource>
<directory>${project.build.directory}/report_templates</directory>
<includes>
<include>**/*</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
Sometimes SVG pictures have to be used and rendered (see ElectricalSafetyCertificate.jrxml
from the TTGAMS project as an example). In this case Batik bridge is required to render SVG in JasperReports and should be introduced as a dependency in tgpsa-pojo-bl\pom.xml
.
<dependency>
<groupId>org.apache.xmlgraphics</groupId>
<artifactId>batik-bridge</artifactId>
<version>1.7</version>
</dependency>
Per aspera ad astra
- Web UI Design and Web API
- Safe Communication and User Authentication
- Gitworkflow
- JavaScript: Testing with Maven
- Java Application Profiling
-
TG Development Guidelines
- TLS and HAProxy for development
- TG Development Checklist
- Entity Properties
- EQL
- Tooltip How To
- All about Matchers
- Streaming data
- Synthetic entities
- Activatable entities
- Jasper Reports
- Opening Compound Master from another Compound Master
- Window management test plan
- Multi Time Zone Environment
- GraphQL Web API
- Guice
- Maven
- Full Text Search
- Deployment recipes
- JRebel Installation and Integration
- Compile-time mechanisms