Java: Reporting Made Easy with DynamicJasper

Author: Emre MORGÜL, Senior SW Engineer – Defence Application SW Group

 

Reporting is one of the most crucial and fundamental part of almost every application. Unfortunately, this process can easily become a programmer’s nightmare depending on demands of users. Programmers need powerful and flexible reporting tools to meet these requirements. Fortunately, there are many reporting tools available for Java. Most powerful and popular one of them is JasperReports [1]. It is quite configurative and provides various features that allow user to generate exceptionally detailed reports. However, JasperReports requires a template to build a report, which complicates things and limits its flexibility. So, what happens if we want to generate dynamic reports?

DynamicJasper [2] is just the right tool for this purpose. It is built upon JasperReports library. Therefore, it takes advantage of all the features JasperReports provides. Besides, it is open source and extraordinarily easy to use. To create a dynamic report, all you need to do is have required libraries and write a few lines of code.

DynamicJasper offers different ways of creating a report. Essentially, it needs a DynamicJasper object to represent a reporting table. To build this object, they provide DynamicReportBuilder class which implements builder design pattern, therefore, it allows an easy and readable way of configuring the table. In addition, DynamicJasper offers other types of ReportBuilder classes that extend DynamicReportBuilder.

In my examples, I will use FastReportBuilder class for simplicity because it automatically handles some of the non-crucial configurations.

Building Simple Report with a Single Table

  • Step 1. Create and configure FastReportBuilder:

The first thing you need to do is create a FastReportBuilder object and configure its general properties.



FastReportBuilder reportBuilder = new FastReportBuilder();
Page page = Page.Page_A4_Landscape();
reportBuilder.setTitle(“Table Name”)
                          .setPageSizeAndOrientation(page)
                          .setUseFullPageWidth(true)
                          .setReportName(“Report Name”);


FastReportBuilder provides many configuration options and every setter method in this class returns itself. Therefore, these method calls can be chained and written in a single line of code. To setup page configurations, they even provide a Page class that can be passed to the report builder as a parameter.

In this example, I covered some of the basic configurations such as setting the title as “Table Name”, page size as A4 and orientation as landscape. There are many other configurations options available in FastReportBuilder, such as adding footer, header, page numbers etc.

  • Step 2. Setup the table structure:

FastReportBuilder has addColumn() methods that accepts either various parameters or an AbstractColumn object. Former ones offer less flexibility but can be used for simple tables.



for (int column = 1; column <= numberOfColumns; column++) {
       reportBuilder.addColumn(“Column “ + column,
       “key” + column,
        String.class.getName(),
        30);
}

 


Parameters for the addColumn() method used in this example, respectively, are given below:

  • Column name
  • Map key to match data with the column (the key is called ‘property’ in this method and is essential for mapping column with actual data)
  • Class name
  • Width of the column

There are other addColumn() methods that accept different number of parameters but this one covers most of the essential configurations.

AbstractColumn gives user more control over columns. For this purpose, they provide the ColumnBuilder class which implements builder design pattern.



for (int column = 1; column <= numberOfColumns; column++) {
        AbstractColumn newColumn =
               ColumnBuilder.getNew()
                                       .setColumnProperty(“key” + column,
                                       String.class.getName())
                                       .setTitle(“Column “ + column)
                                       .setWidth(30)
                                      .build();
reportBuilder.addColumn(newColumn);
}


Essentially, both of these methods do the same thing. However, AbstractColumn offers many more configuration options and is easier to use.

Additionally, it is possible to set cell styles for both headers and details of the table. For this purpose, they provide the Style class. It has configuration options for setting border, transparency, alignment, font, orientation, text color, background color etc.

  • Step 3. Setup the data structure:

Preparing the data structure for the generated table is the tricky part. To feed actual data into a table, we need to generate a separate HashMap object for each row. Key value used while adding a column is critical in this step. For example, if we used key (property) ‘idColumn’ for our column creation, we map data to that column as HashMap.put(“idColumn”, DATA). Finally, we need to collect all these HashMaps in a List object (preferably an ArrayList). Each of these HashMaps represents a single row of our table.



List rowsDataList = new ArrayList();

for (int row = 1; row <= numberOfRows; row++) {
        HashMap<String, String> rowHashMap = new HashMap<>();
        for (int column = 1; column <= numberOfColumns; column++) {
                rowHashMap.put(“key” + column,
                                             “Row” + row + ” Column “ + column);
}
        rowsDataList.add(rowHashMap);
}


  • Step 4. Insert data into table:

JasperPrint object is our final report object, which contains the table along with inserted rows. We need to use a DynamicReport object to create a JasperPrint object. Calling our FastReportBuilder object’s build() method converts it into a DynamicReport object. Then we need to match our data structure with this DynamicReport object.



DynamicReport dynamicReport = reportBuilder.build();
JasperPrint finalReport = DynamicJasperHelper.generateJasperPrint(dynamicReport,
                                                                                                     new ClassicLayoutManager(),
                                                                                                           rowsDataList);


  • Step 5. Export final report to a file in desired format:

Finally, we can export this generated report object into desired data format. JasperReports provide many file exporter classes for different types of data format. Supported data formats in JasperReports are PDF, HTML, XLS, RTF, ODT, CSV, TXT and XML. It is possible to set additional configurations while exporting into a file.

Excel Exporter Example:



JRXlsExporter xlsExporter = new JRXlsExporter();
ExporterInput exporterInput = new SimpleExporterInput(finalReport);
OutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(filePath);
xlsExporter.setExporterOutput(exporterOutput);
xlsExporter.setExporterInput(exporterInput);


SimpleXlsReportConfiguration configuration = new SimpleXlsReportConfiguration();
configuration.setOnePagePerSheet(false);
configuration.setWhitePageBackground(true);
configuration.setRemoveEmptySpaceBetweenColumns(false);
xlsExporter.setConfiguration(configuration);


xlsExporter.exportReport();


PDF Exporter Example:



JRPdfExporter pdfExporter = new JRPdfExporter();
ExporterInput exporterInput = new SimpleExporterInput(finalReport);
OutputStreamExporterOutput exporterOutput = new SimpleOutputStreamExporterOutput(filePath);
pdfExporter.setExporterOutput(exporterOutput);
pdfExporter.setExporterInput(exporterInput);


SimplePdfReportConfiguration configuration = new SimplePdfReportConfiguration();configuration.setIgnoreHyperlink(true);
pdfExporter.setConfiguration(configuration);


pdfExporter.exportReport();


Additionally, you can use JasperReports’ built-in JasperViewer class to preview your final report. This viewer also allows user to print or save the report in any of the provided formats.





JasperViewer.viewReport(finalReport);


Final PDF file generated in this example is shown below:

Even though, this is the simplest report you can generate with DynamicJasper, it covers all the necessary steps needed for creating reports with variable number of columns and rows. Yet, it does not demonstrate any of the more advanced capabilities of DynamicJasper.

DynamicJasper is not limited to reports that only have a single table. On the contrary, it is possible to generate reports that have any number of concatenated tables and subreports. Besides, it provides many visual configurations that can be applied to these tables. Furthermore, DynamicJasper offers various charts that can be easily generated and configured. Programmers can use these charts to produce complex reports. However, purpose of this post is simply to introduce DynamicJasper and show its basics. Other topics will be covered thoroughly in the future.

REFERENCES

[1] https://community.jaspersoft.com/

[2] http://dynamicjasper.com/

 

Leave a Reply

Your email address will not be published.