Spring Web MVC - Spring Web Flow Working With JasperReports
An important requirement in a lot of applications is reporting. It can be internal reports (same application jsp/html) or to an external format like xls,pdf or xml etc. A popular reporting engine is JasperReports. In the past few months I have seen a common posting theme in Spring Community Forums (even asking me via email) related about integration between JasperReports with Spring Web MVC and Spring Web Flow (SWF) and especially with Hibernate
A common architectural pattern is Model-View-Controller (MVC). A situation would be as follows:
Some user from the View layer (jsp/html) would click some button to request a desired report (i.e pdf,xls); the request should be handled in the Controller layer ( a controller class for Spring Web MVC or Action class for SWF), the controller/Action should call the Model layer(Service/BO) to delegate its work in that layer. The Service/BO would call DAO classes to get some data (rows from the database to fill and generate the report). After that, the Service/BO should send the report back to the Controller layer which should then send the report to the View layer.
Furthermore, a common approach when you work with Spring is to use Hibernate. If you work with Hibernate, we are using POJO classes to represent our entities, or instance Customer, Provider, etc. A simple report would be a list of all our Customers and other perhaps all our Providers, then, it logical working with a list (i.e. ArrayList) for these entities.
In my experience,many applications require some complex reports. For instance, maybe a special report required by your boss. After some analysis, you can conclude that a solution would be the result of do a query in the database working with two to six entities related (or even worst not related!). Here Hibernate would be not so useful, so the classic SQL query syntax is required (JOIN clause in this case) - you can use jdbcTemplate instead of Hibernate here.
Now suppose that for these six tables, each one has twenty fields and for your report you only need four fields of each table, then we have another problem. You are retrieving a lot of fields that you don't need. I used to work with my own wrap classes, now the question would be, how do I know what fields or variables I must create for my wrapclass?. The solution is this, from your yourreport.jrxml, open it and you must see something like (about structure)
<field name="idCustomer" class="java.lang.String"/> <field name="nameCustomer" class="java.lang.String"/> <field name="phoneCustomer" class="java.lang.String"/>
Dont forget that you can design your own reports using the IReport tool. Then when you write your own sql statements (with/inside IReport of course) to test your reports, in the same time implicitly in a dynamic way, you are creating a "<field..." for each field retrieved from the query. Each field should be a variable in your wrap class
For this example and for tutorial purposes I will create a simple wrap class and avoid the DB connection. Before we start consider these situations:
- If you are working with SWF the last page of your flow process (i.e: 5/5 ) should let you finish the process or generate a pdf report, you can choose one of them. If you choose the report, it should open a pdf report (Adobe Reader would be executed) but not disposing the last jsp page of the flow process, to let you finish the flow. The other case is when you arrive to the last jsp page and you don't want the report yet, then you only finish the flow process.
- If in the flow process mentioned above you didn't generate the report and terminated the process, but after of some time now it is need it, you would call some option in the web menu and request the desired report (maybe provide some request parameter) - for this case it is enough to use the Spring Web MVC. SWF wouldn't be logical here
Now you should have clear that SWF and Spring Web MVC need call the same Service/BO and retrieve the desired report.
Before to start, the frameworks and other tools used (no all are really necessary)
- Spring 2.5.0
- Spring Web Flow 1.0.5
- JasperReports 2.0.3
- Eclipse 3.4
- Tomcat 5.5.25
- TomcatPlugin 3.2.1
- Spring IDE 2.1.0
This tutorial assumes basic-medium level about Spring and its sub-projects
(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)





Comments
Pierre Teddy replied on Fri, 2009/05/15 - 12:18pm
Balu Ramesh replied on Sat, 2009/06/13 - 4:03am
VIJAYASARADHI P... replied on Tue, 2009/08/18 - 10:56pm
Raj Dzone replied on Sun, 2009/09/27 - 9:47pm
Kacper Zizulewski replied on Fri, 2009/11/13 - 5:24am
Manuel Jordan replied on Sat, 2009/11/14 - 10:23pm
Hello Guys
The source is almost available.
My hard disk crushed months ago, and the source code is somewhere among many DVD,
Regards
Raj Dzone replied on Thu, 2010/03/04 - 1:35am
Manuel Jordan replied on Mon, 2010/03/22 - 8:58pm
Hello Dear Members
At last I found the source code, soon I going to upload the code in my blog
My Best Regards
Sawan Yadav replied on Mon, 2010/04/26 - 6:31am
Manuel Jordan replied on Tue, 2010/04/27 - 7:44am
in response to:
Sawan Yadav
Hello sawan, in this weekend would be available in my Blog.
Yash Negi replied on Thu, 2010/06/24 - 9:04am
in response to:
Manuel Jordan
Manuel Jordan replied on Thu, 2010/06/24 - 7:51pm
in response to:
Yash Negi
Hello Yash, this weekend the code going to be available
Yash Negi replied on Fri, 2010/06/25 - 1:43am
Yash Negi replied on Sat, 2010/06/26 - 3:08pm
Manuel Jordan replied on Tue, 2010/06/29 - 3:13pm
Dear Members:
Source code finally available, you can download from here
Zenith Zhao replied on Wed, 2010/11/24 - 5:46pm
The tutorial is helpful in general. Thanks.
But,
1)
context.getRequestScope().put("datasource",datasource); does not work in my case.
The result pdf is blank!! I debugged one afternoon and found out that all field values are null.
Then, I put the data source to the flow scope (as shown below) and it worked.
context.getFlowScope().put("datasource",datasource);
2)
If you only has one data source, do not set the reportDataKey in the views.properties file.
Otherwise, you will get an exception. the views.peroperties file should look as follows.
reportView.(class)=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
reportView.url=/WEB-INF/report/reportName.jasper
BTW:
the use of JRBeanCollectionDataSource is not necessary. you can simly use a List.
Manuel Jordan replied on Fri, 2010/11/26 - 12:31pm
in response to:
Zenith Zhao
Jate Wiset replied on Thu, 2011/04/07 - 2:19pm
Sanjaydath Anan... replied on Mon, 2011/07/04 - 1:37am
Manuel Jordan replied on Mon, 2011/07/04 - 8:49am
in response to:
Sanjaydath Ananthaneni
Hello
Thanks for your kind words, enjoy my work and be always reasearching and share some day some code =)