Tuesday, December 21, 2010

Spring 3 MVC - Jasper: Sub-reports Tutorial

In this tutorial we will integrate Jasper reporting with a simple Spring 3 MVC application. We will create a master report and a sub-report to display our data. To design the report layout we will use iReport to create the template. If you're not familiar yet with integrating a simple report, I suggest you read my other tutorial: Spring 3 MVC - Jasper Integration Tutorial

What is Jasper Reports?
JasperReports is the world's most popular open source reporting engine. It is entirely written in Java and it is able to use data coming from any kind of data source and produce pixel-perfect documents that can be viewed, printed or exported in a variety of document formats including HTML, PDF, Excel, OpenOffice and Word.

Source: http://jasperforge.org/projects/jasperreports

What are Sub-reports?
Sub-reports are normal Jasper reports. They're called sub-reports because they are embedded within a report. The structure and data access is essentially the same.

Similar with our previous tutorial. We will setup our Spring 3 MVC application first. If you need a review with Spring MVC, I suggest you read the other tutorials I've posted. Or you can also Google for related tutorials.

The image below is an actual screenshot of our report without the sub-report. If you want to learn how to generate the report below, please visit the following link: Spring 3 MVC - Jasper Integration Tutorial


With sub-report added, here's the new image:

We added two extra fields. These two fields are located in the sub-report. These fields are place on the Summary section of the report layout. If you place these fields on the Detail band, the data will be repeated as many times as the number of rows in your datasource.

Using iReport we can generate both report layouts. On the final document, the master and sub-report are merged as if there's only a single document.

Here's the master report:

The highlighted gray rectangle indicates an embedded sub-report. The format is exactly the same as we had in our previous Jasper tutorial. If you need to a refresher, feel free to read that tutorial first.

Here's the sub-report:

Notice we declared two Parameters here: a LOCATION and MANUFACTURER parameter. I emphasized Parameters not Fields because those two terms are different. We can save ourselves some headache by just declaring these parameters in the master report directly, so that we don't have to create a sub-report. But where's the joy in that? We want to learn sub-report because it provides other benefits besides just adding simple parameters.

Here's the JRXML document for the sub-report:
tree-template_subreport1.jrxml

Here's the structure of our project:

Besides the Spring XML files, these are all the files we need for this project.

We can now begin our project.

Our first task is to setup the main controller that will handle the download request.

This controller declares three mappings:
/download - for showing the download page
/download/xls - for retrieving the actual Excel report
/download/pdf - for retrieving the actual PDF report

If you notice in each request handlers, we return an instance of ModelAndView. The view names are declared on a separate XML file under /WEB-INF/jasper-views.xml
jasper-views.xml

We have declared four beans in this XML file. Each bean uses a Spring built-in view for Jasper that corresponds to a specific format. Take note of these special properties for each view:
id
url
reportDateKey
subReportUrls
subReportDataKeys

Also take note of the following sub-report variables:
JasperCustomSubReportLocation
JasperCustomSubReportDatasource

We declared these two variables in the master JRXML report file named tree-template.jrxml.

First, in the headers:

Second, in the subreport element:

If you want to see the whole JRXML file, you can find it in the downloadable project at the end of this tutorial. If you look carefully at the following line:

We have basically wrapped our sub-report datasource JasperCustomSubReportDatasource with a JRBeanCollectionDataSource. This is important if you want to see your data repeated over multiple rows. Otherwise, all your data will be consumed by the first record. See this post at SpringSource forums for more info.

Let's examine further the contents of the subreport element:

Here we're referencing two sub-report parameters: LOCATION and MANUFACTURER. These parameters are declared inside the sub-report JRXML file itself. For each parameter, we declare how we populate this parameter. We're basically instructing Jasper "Hey, Jasper this is what you need to do when you encounter this parameter". For example, in the LOCATION parameter, we wrote:
[CDATA[$F{location}]]

This means take and assign the value of the Field location.

Take note that LOCATION and location are not the same in this tutorial. LOCATION is a Parameter that we declared in the sub-report file; whereas location is a Field we declared in the master report file.

If you examine the header of the master report file, you'll see the following field declarations:

The same thing goes for the parameter MANUFACTURER and the field manufacturer.

If you look back at the MainController, the master report and the sub-report share the same datasource. How does our datasource looks like?


Our datasource is a simple array list populated with simple POJO instances.

Sales


Our application is almost finished. We just need to setup some required Spring configuration files.

To enable Spring MVC we need add it in the web.xml

web.xml

Take note of the URL pattern. When accessing any pages in our MVC application, the host name must be appended with
/krams

In the web.xml we declared a servlet-name spring. By convention, we must declare a spring-servlet.xml as well.

spring-servlet.xml

By convention, we must declare an applicationContext.xml as well.

applicationContext.xml

Our application is now finished. We've managed to setup a simple Spring 3 MVC application with reporting capabilities. Thanks to Jasper. We've managed to add a master report and a sub-report successfully. We've also leveraged Spring's MVC programming model via annotation.

To access the download page, enter the following URL:
http://localhost:8080/spring-jasper-subreport-single/krams/main/download

If you want to download the report directly, enter the following URL for XLS format:
http://localhost:8080/spring-jasper-subreport-single/krams/main/download/xls

For PDF format, enter the following URL:
http://localhost:8080/spring-jasper-subreport-single/krams/main/download/pdf

For HTML and CSV, I left this exercise for my readers.

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-mvc-jasper-integration-tutorial/

You can download the project as a Maven build. Look for the spring-jasper-subreport-single.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

If you want to learn more about Spring MVC and Jasper, feel free to read my other tutorials in the Tutorials section.

For more info about Sub-reports, check the following:
Spring Framework Reference: Chapter 17.7 JasperReports
JasperForge: Subreports! by Giulio Toffoli
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring 3 MVC - Jasper: Sub-reports Tutorial ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Monday, December 20, 2010

Spring 3 MVC - Jasper Integration Tutorial

In this tutorial we will integrate Jasper reporting with a simple Spring 3 MVC application. We will provide a custom data source where Jasper will retrieve its data. We will use Spring's built-in Jasper support to render our report in Excel, PDF, HTML, and CSV formats. To design the report layout we will use iReport to create the template.

Note: I suggest reading the following updated tutorial instead:
Spring MVC 3.1 and JasperReports: Using iReport and AJAX

What is Jasper Reports?
JasperReports is the world's most popular open source reporting engine. It is entirely written in Java and it is able to use data coming from any kind of data source and produce pixel-perfect documents that can be viewed, printed or exported in a variety of document formats including HTML, PDF, Excel, OpenOffice and Word.

Source: http://jasperforge.org/projects/jasperreports
What is iReport?
iReport is the free, open source report designer for JasperReports. Create very sophisticated layouts containing charts, images, subreports, crosstabs and much more. Access your data through JDBC, TableModels, JavaBeans, XML, Hibernate, CSV, and custom sources. Then publish your reports as PDF, RTF, XML, XLS, CSV, HTML, XHTML, text, DOCX, or OpenOffice.

Source: http://jasperforge.org/index.php?q=project/ireport
Similar with our previous tutorial. We will setup our Spring 3 MVC application first. If you need a review with Spring MVC, I suggest you read the other tutorials I've posted. Or you can also Google for related tutorials.

Here's a screenshot of the report that we will be generating:


This is just basic. You can add more features such as charts,custom calculations, and other report related functions with Jasper. If you need to design the layout, you can use iReport to do the job.

Our first task is to setup the main controller that will handle the download request.

This controller declares three mappings:
/main/download - for showing the download page
/main/download/xls - for retrieving the actual Excel report
/main/download/pdf - for retrieving the actual PDF report
To add support for HTML and CSV formats, just copy any of the methods. Rename the value of the @RequestMapping and follow the pattern. I will leave that part as an exercise for my reader.

In each request handler, we return the datasource:

We then placed the datasource in the a Map:

Then we added it to the ModelAndView.
For XLS, we did the following:
modelAndView = new ModelAndView("xlsReport", parameterMap);

And for PDF, we did the following:
modelAndView = new ModelAndView("pdfReport", parameterMap);

The only thing that changed are the view names: xlsReport and pdfReport. These view names are declared on a separate XML file under /WEB-INF/jasper-views.xml

jasper-views.xml

We've declared four beans in this config. Each bean uses a Spring built-in view for Jasper that corresponds to a specific format. For example, JasperReportsXlsView is used for rendering Excel reports.

Each report has a reportDataKey that references the datasource from the controller. It also has a reference to the Jasper template tree-template.jrxml

Let's complete our Spring MVC setup.

To enable Spring MVC we need add it in the web.xml

web.xml

Take note of the URL pattern. When accessing any pages in our MVC application, the host name must be appended with
/krams

In the web.xml we declared a servlet-name spring. By convention, we must declare a spring-servlet.xml as well.

spring-servlet.xml

Notice we declared two view resolvers here: an InternalResourceViewResolver and an XmlViewResolver. If you've been following my other tutorials, you'll notice that we always declare an InternalResourceViewResolver only.

We must declare an extra view resolver this time to help Spring to choose the correct view to render our reports. If we just use InternalResourceViewResolver, all view references will point to /WEB-INF/jsp/ and will be appended with a .jsp extension. We don't want that because that location is for JSPs. Our report views are internal within Spring's package and we indicate that inside the /WEB-INF/jasper-views.xml file.

We're done with the spring-servlet.xml file.

By convention, we must declare an applicationContext.xml as well.

applicationContext.xml

This XML config declares three beans to activate the Spring 3 MVC programming model.

Now we move to the crucial point of our tutorial. Remember earlier we had a reference to a template file named tree-template.jrxml

tree-template.jrxml (a partial view)

If you notice our report template is just plain XML! Nothing magical here. Actually we used a special tool to generate this XML template. It's called iReport. To get started with this tool, visit the Getting Started guide from JasperForge.

For this tutorial, we need to do the following:

1. Download and install iReport.

2. Run iReport

3. Go to File. Then click on New

4. Select the Tree template . Any template will do, even a blank one.


You should see a ready-made template:


5. We need to add four new fields in this layout. On the upper-left side, click on Fields.


6. Right-click and add four fields:


7. Make sure to set the correct types:
id: Long
name: String
price: Double
description: String

On the upper-right side, there's a panel where you can modify the properties of the fields we declared.


8. Now we need to drag each of those fields to the main layout. See below:


9. Then modify the title and subtitle. This isn't really mandatory. Just make sure you placed those four fields.


10. Click on the main layout again. On the right-side panel, you should see a list of properties for the main report layout. You need to change the default Language from Groovy to Java. Failure to do so will result to multiple compilation errors. Unless you know Groovy and familiar with its dependencies, it's best you stick with Java for now.


11. Save the document.

12. Now you need to locate that document. Copy and place it in the classpath of your web application. If you look carefully on the directory where the original document is saved, there are two images that had been saved as well. Make sure to copy them as well! Failure to copy them to your classpath will cause an Exception in the application.

Here's how our final directory should look like:

Remember we declared four fields in this layout. Where exactly do we get our data to fill-in these fields? It's assigned by the controller.

See that line:
JRDataSource datasource  = dataprovider.getDataSource();
That's where we get our data.

The datasource
Here we provide a custom datasource made from in-memory list of Sales items. We use the DAO name here to indicate that the data can come from a DAO or other persistence means.

SalesDAO

Our datasource returns a list of Sales. This is a simple Data Transfer Object for containing our data from the database.
Sales

Our application is now finished. We've managed to setup a simple Spring 3 MVC application. Then we added reporting using Jasper. We use Spring's built-in support to render the Jasper views. We've used iReport to design the report document. We've also leveraged Spring's MVC programming model via annotation.

To access the download page, enter the following URL:
http://localhost:8080/spring-djasper-integration/krams/main/download

Here's a final look to our download page:

downloadpage.jsp

If you want to download the report directly, enter the following URL for XLS format:
http://localhost:8080/spring-jasper-integration/krams/main/download/xls

For PDF format, enter the following URL:
http://localhost:8080/spring-jasper-integration/krams/main/download/pdf

For HTML and CSV, I left this exercise for my readers.

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-mvc-jasper-integration-tutorial/

You can download the project as a Maven build. Look for the spring-jasper-integration.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

If you want to learn more about Spring MVC and Jasper, feel free to read my other tutorials in the Tutorials section.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring 3 MVC - Jasper Integration Tutorial ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share

Sunday, December 19, 2010

Spring 3 MVC - DynamicJasper Integration Tutorial

In this tutorial we will integrate DynamicJasper with a simple Spring 3 MVC application. We will provide a custom data source where DynamicJasper will retrieve its data. The application will be layered so that we can easily modify the features or implementations of our application.

What is DynamicJasper?
DynamicJasper (DJ) is an open source free library that hides the complexity of Jasper Reports, it helps developers to save time when designing simple/medium complexity reports generating the layout of the report elements automatically.

Source: http://dynamicjasper.com/

What is JasperReports?
JasperReports is the world's most popular open source reporting engine. It is entirely written in Java and it is able to use data coming from any kind of data source and produce pixel-perfect documents that can be viewed, printed or exported in a variety of document formats including HTML, PDF, Excel, OpenOffice and Word.

Source: http://jasperforge.org/projects/jasperreports

Similar with our previous tutorial. We will setup our Spring 3 MVC application first. If you need a review with Spring MVC, I suggest you read the other tutorials I've posted. Or you can also Google for related tutorials.

Here's a screenshot of the report document that we will be generating:

This is just basic. You can add and show more features with Jasper and DynamicJasper. For now, we'll stick with the basics.

Our first task is to setup the main controller that will handle the download request.

MainController

This controller declares two mappings:
/download - for showing the download page
/download/xls - for retrieving the actual Excel report

Examine the doSalesReportXLS() controller method. It has a reference to a download service named downloadService. This service handles the actual report processing. Later, we'll discuss that in-depth.

The /download mapping will display the downloadpage view which resolves to /WEB-INF/jsp/downloadpage.jsp

downloadpage.jsp

This is a simple JSP. It has an HTML link for downloading the report. Notice the URL points to /krams/main/download/xls. The same mapping we have in the MainController.

Here's a screenshot of this page:

Next, we enable Spring MVC in the web.xml

web.xml

Take note of the URL pattern. When accessing any pages in our MVC application, the host name must be appended with
/krams

In the web.xml we declared a servlet-name spring. By convention, we must declare a spring-servlet.xml as well.

spring-servlet.xml

This XML config declares a view resolver. All references to a JSP name in the controllers will map to a corresponding JSP in the /WEB-INF/jsp location.

By convention, we must declare an applicationContext.xml

applicationContext.xml

This XML config declares three beans to activate the Spring 3 MVC programming model.

Let's return back to DynamicJasper.

If you remember back in the MainController we declared a reference to a DownloadService which is automatically injected by Spring.

The DownloadService is a delegate. All reporting processing is handled by this service.

DownloadService

To generate the report, we call the downloadXLS() method. This generates an Excel report. Let's examine further how the report is generated:

1. Retrieve an instance of our datasource:
SalesDAO datasource = new SalesDAO();
JRDataSource ds = datasource.getDataSource();

The datasource can come from a variety of sources like from an in-memory list, database, and alike. Later, we'll show what's inside this SalesDAO

2. Generate the Jasper layout:
ReportLayout layout = new ReportLayout();
DynamicReport dr = layout.buildReportLayout();

The layout is like the template of your report. It's basically the design of how you want the report to look like. Our Jasper layout is actually generated on the fly by DynamicJasper. That's the main purpose of DynamicJasper. It will dynamically, programmatically generate the layout. This is useful for generating tabular reports which are mostly used for professional applications. If you need to manually design or create an artistic layout, I advise you try layouting using Jasper's native JRXML format. DynamicJasper can also use a JRXML template, but that's beyond the scope of this tutorial.

3. Compile the Jasper layout into a JasperReport object:
JasperReport jr = DynamicJasperHelper.generateJasperReport(dr, new ClassicLayoutManager(), params);

The JasperReport object is the compiled version of your layout that can be understood by Jasper. Imagine it like this: the layout is for humans, while the compiled object is for the computer.

4. Create the Jasper print:
JasperPrint jp = JasperFillManager.fillReport(jr, params, ds);

This basically fills the JasperReport with contents from the datasource.

5. Export the report to your desired format. For this tutorial we will export it as an
Excel document.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Exporter exporter = new Exporter();
exporter.export(jp, baos);

Here we pass an instance of a ByteArrayOutputStream and a JasperPrint object.

6. Set the response header and content type:
String fileName = "SalesReport.xls";
response.setHeader("Content-Disposition", "inline; filename="+ fileName);
response.setContentType("application/vnd.ms-excel");
response.setContentLength(baos.size());

Make sure you set the correct contentType.

7. Write the report to the output stream:
writeReportToResponseStream(response, baos);

Now, let's examine the remaining classes.

The ReportLayout
This is a custom wrapper to DynamicJasper's FastReportBuilder. The purpose of this class is to encapsulate the layout of the report. This isn't mandatory. You can remove the contents of buildReportLayout() and place it along with the DownloadService. Take note we're encapsulating a DynamicJasper feature here, not a Jasper. So if you have specific questions about these, make sure to search the DynamicJasper forums.

The Exporter
This is a custom wrapper to Jasper's JRXlsExporter. The purpose of this class is to encapsulate the exporting of the report to different formats. This isn't mandatory. You can remove the contents of export() and place it along with the DownloadService. Take note we're encapsulating a Jasper feature here, not a DynamicJasper. So if you have specific questions about these, make sure to search the Jasper forums.

The datasource
Here we provide a custom datasource made from in-memory list of Sales items. We use the DAO name here to indicate that the data can come from a DAO or other persistence means.

SalesDAO

Our datasource returns a list of Sales. This is a simple Data Transfer Object for containing our data from the database.

Sales

Our application is now finished. We've managed to setup a simple Spring 3 MVC application. Then we added reporting using DynamicJasper. We've divided our application's concerns in various layers: controllers, services, DAO, layout, and exporter so that we can easily change implementation and custom processing. We've also leveraged Spring's MVC programming model via annotation.

To access the download page, enter the following URL:
http://localhost:8080/spring-djasper-integration/krams/main/download


If you want to download the report directly, enter the following URL:
http://localhost:8080/spring-djasper-integration/krams/main/download/xls

The best way to learn further is to try the actual application.

Download the project
You can access the project site at Google's Project Hosting at http://code.google.com/p/spring-mvc-dynamicjasper-integration-tutorial/

You can download the project as a Maven build. Look for the spring-djasper-integration.zip in the Download sections.

You can run the project directly using an embedded server via Maven.
For Tomcat: mvn tomcat:run
For Jetty: mvn jetty:run

If you want to learn more about Spring MVC and Jasper, feel free to read my other tutorials in the Tutorials section.
StumpleUpon DiggIt! Del.icio.us Blinklist Yahoo Furl Technorati Simpy Spurl Reddit Google I'm reading: Spring 3 MVC - DynamicJasper Integration Tutorial ~ Twitter FaceBook

Subscribe by reader Subscribe by email Share