Jasper reports on Vaadin sample
Introduction
I meet JasperReports some years ago and I liked this report library; this year I did need to implement a report on a personal project using Vaadin, but surprisingly I was not able to found a sample of this, so I did this little sample and article.
First, you will need a JDK Maven and Mysql in order to try the sample, and you can download the code here: http://sourceforge.net/projects/jrtutorial/files/VaadinJRSample/
There is a README.txt file you can follow in order to run the sample, basically you need to:
Create database running resources/database.sql on Mysql or MariaDB
Compile the entire project: run “mvn install”.
Deploy the application in Jetty: run “mvn jetty:run”
Go to http://localhost:8080/ in your browser
Implementation
Let’s see the sample code step by step.
The data is only a person table with some data.
The main class MyUI.java has two UI components (the report generating button and a list component used to show current data in database.):
Java
final Button reportGeneratorButton = new Button("Generate report");
…
layout.addComponent(reportGeneratorButton);
layout.addComponent(new PersonList());
The list is implemented on PersonList.java, I am using a FilteringTable (https://vaadin.com/directory/component/filteringtable), that loads the data using a Vaadin SQLContainer:
Java
SQLContainer container=null;
…
TableQuery tq = new TableQuery("person", new ConnectionUtil().getJDBCConnectionPool());
container = new SQLContainer(tq);
filterTable = buildPagedTable(container);
And the SQLContainer is provided with a JDBCConnectionPool created from a properties file (resources/database.properties):
Java
Properties prop=PropertiesUtil.getProperties();
…
public JDBCConnectionPool getJDBCConnectionPool(){
JDBCConnectionPool pool = null;
try {
pool = new SimpleJDBCConnectionPool(
prop.getProperty("database.driver"),
prop.getProperty("database.url"),
prop.getProperty("database.userName"),
prop.getProperty("database.password"));
} catch (SQLException e) {
e.printStackTrace();
}
return pool;
The report generation is implemented on ReportGenerator class, this class loads the report template:
Java
File templateFile=new File(templatePath);
JasperDesign jasperDesign = JRXmlLoader.load(templateFile);
Compile report template:
Java
jasperReport = JasperCompileManager.compileReport(jasperDesign);
Fill report with data:
Java
HashMap fillParameters=new HashMap();
JasperPrint jasperPrint = JasperFillManager.fillReport(
jasperReport,
fillParameters,
conn);
Export the jasperPrint object to Pdf format:
Java
JRPdfExporter exporter = new JRPdfExporter();
exporter.setExporterInput(new SimpleExporterInput(jasperPrint));
exporter.setExporterOutput(new SimpleOutputStreamExporterOutput(outputStream));
exporter.exportReport();
And finally execute all the logic to generate the report and sent it to an OutputStream:
Java
JasperDesign jasperDesign=loadTemplate(templatePath);
setTempDirectory(templatePath);
JasperReport jasperReport=compileReport(jasperDesign);
JasperPrint jasperPrint=fillReport(jasperReport, conn);
exportReportToPdf(jasperPrint, outputStream);
But all the logic at ReportGenerator.java is called from the ReportUtil class, this class is the responsible to connect Vaadin layer with ReportGenerator layer. There are two methods: the first one is prepareForPdfReport, this method creates a database connection, generates the report as a StreamResource (calling the another method) and finally extends the source button with a FileDownloader component in order to upload the generated report stream, so all the uploading magic is done by FileDownloader extension (https://vaadin.com/api/com/vaadin/server/FileDownloader.html):
Java
Connection conn=new ConnectionUtil().getSQLConnection();
reportOutputFilename+=("_"+getDateAsString()+".pdf");
StreamResource myResource =createPdfResource(conn,reportTemplate,reportOutputFilename);
FileDownloader fileDownloader = new FileDownloader(myResource);
fileDownloader.extend(buttonToExtend);
The second method createPdfResource, uses ReportGenerator class in order to return the generated report as a StreamResource:
Java
return new StreamResource(new StreamResource.StreamSource() {
@Override
public InputStream getStream () {
ByteArrayOutputStream pdfBuffer = new ByteArrayOutputStream();
ReportGenerator reportGenerator=new ReportGenerator();
try {
reportGenerator.executeReport(baseReportsPath+templatePath, conn, pdfBuffer);
} catch (JRException e) {
e.printStackTrace();
}
return new ByteArrayInputStream(
pdfBuffer.toByteArray());
}
}, reportFileName);
So, in order to call the report generator process when only need to call ReportUtil like we did in ‘MyUI.java’:
Java
final Button reportGeneratorButton = new Button("Generate report");
new ReportsUtil().prepareForPdfReport("/reports/PersonListReport.jrxml",
"PersonList",
reportGeneratorButton);
Finally, the jasper report design can be found in the WEB-INF/personListReport.jrxml file
This is a picture of the sample running and the generated report:
And that’s all, I expect to help someone with this sample, thanks for reading.