Skip to content

Jasper reports

Rowdy edited this page Jun 4, 2019 · 24 revisions

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.

Development of Jasper reports

Tools

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.

Templates

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.

Report Styles

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.

Images

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.

Representing of data

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.

Development of sub-reports

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.

Including sub-report into the main report

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.

How to include a Jasper report into TG based application

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.

How to produce a PDF file and present it for printing

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>
Clone this wiki locally