A Peruvian Analyst, Designer and Java Programmer that enjoys working with frameworks like Spring, Hibernate and others, Playing with Java and compositing Music, some interests are Playing bass and guitar, listening to music (Pink Floyd, Rick Wakeman), reading the Bible and normally buying and reading Java books, here my Blog http://manueljordan.wordpress.com/ Manuel has posted 31 posts at DZone. View Full User Profile

Spring Web MVC - Spring Web Flow Working With JasperReports

10.13.2008
| 108066 views |
  • submit to reddit

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

 

Published at DZone with permission of its author, Manuel Jordan.

(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

Is there source code for this?

Balu Ramesh replied on Sat, 2009/06/13 - 4:03am

Very interesting article. Where is the code ?

VIJAYASARADHI P... replied on Tue, 2009/08/18 - 10:56pm

This is very good article.. where can I get the Source code?

Raj Dzone replied on Sun, 2009/09/27 - 9:47pm

The article is gud ..can i get the source code

Kacper Zizulewski replied on Fri, 2009/11/13 - 5:24am

Helpful article, any chances to get a source code ?

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

Hi good article.. can i get the source code...

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

Hi , When will you post your source code.Please let me know . Thanks Sandy

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

can you please provde the link for the source code, I can't see it anywhere... thanks i advance... this article really going to help me what I trying to do...

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

thanks for quick reply.... where I can see the code???? And below is my requirement , if you have some suggestion... On the web-interface I have a tab called excel... when user click on the excel the data fetch should export in the csv format....

Yash Negi replied on Sat, 2010/06/26 - 3:08pm

where I can see the code, as you said the code will be available this week end... I really looking for this...

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

My source code is fine, I don't receive none exception, all work fine, go to my Blog and download the source code and test it 

Jate Wiset replied on Thu, 2011/04/07 - 2:19pm

thank many for good

Sanjaydath Anan... replied on Mon, 2011/07/04 - 1:37am

its damn good. its very useful one who have no knowledge about how to integrate spring and jasper and hibernate. thanks manuel

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 =)

Herman Fouetieu replied on Tue, 2014/11/25 - 4:29am

HI MANUEL,

I have follow  all the steps of the Tutorial and everyting ok.

but when i try to access to a report design with and compile with ireport 5, i have the following exception.

Please help me to solve that.

Etat HTTP 500 - Request processing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mbamsusers': Initialization of bean failed; nested exception is java.lang.ClassCastException: cannot assign instance of net.sf.jasperreports.engine.base.JRBaseStyle to field net.sf.jasperreports.engine.base.JRBaseParagraph.paragraphContainer of type net.sf.jasperreports.engine.JRParagraphContainer in instance of net.sf.jasperreports.engine.base.JRBaseParagraph

type Rapport d'exception

message Request processing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mbamsusers': Initialization of bean failed; nested exception is java.lang.ClassCastException: cannot assign instance of net.sf.jasperreports.engine.base.JRBaseStyle to field net.sf.jasperreports.engine.base.JRBaseParagraph.paragraphContainer of type net.sf.jasperreports.engine.JRParagraphContainer in instance of net.sf.jasperreports.engine.base.JRBaseParagraph

description Le serveur a rencontré une erreur interne qui l'a empêché de satisfaire la requête.

exception

org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mbamsusers': Initialization of bean failed; nested exception is java.lang.ClassCastException: cannot assign instance of net.sf.jasperreports.engine.base.JRBaseStyle to field net.sf.jasperreports.engine.base.JRBaseParagraph.paragraphContainer of type net.sf.jasperreports.engine.JRParagraphContainer in instance of net.sf.jasperreports.engine.base.JRBaseParagraph
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:583)
	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
cause mère

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'mbamsusers': Initialization of bean failed; nested exception is java.lang.ClassCastException: cannot assign instance of net.sf.jasperreports.engine.base.JRBaseStyle to field net.sf.jasperreports.engine.base.JRBaseParagraph.paragraphContainer of type net.sf.jasperreports.engine.JRParagraphContainer in instance of net.sf.jasperreports.engine.base.JRBaseParagraph
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:478)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
	java.security.AccessController.doPrivileged(Native Method)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
	org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
	org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
	org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
	org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
	org.springframework.web.servlet.view.ResourceBundleViewResolver.initFactory(ResourceBundleViewResolver.java:244)
	org.springframework.web.servlet.view.ResourceBundleViewResolver.loadView(ResourceBundleViewResolver.java:186)
	org.springframework.web.servlet.view.AbstractCachingViewResolver.createView(AbstractCachingViewResolver.java:159)
	org.springframework.web.servlet.view.AbstractCachingViewResolver.resolveViewName(AbstractCachingViewResolver.java:78)
	org.springframework.web.servlet.DispatcherServlet.resolveViewName(DispatcherServlet.java:1205)
	org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1154)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:901)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
cause mère

java.lang.ClassCastException: cannot assign instance of net.sf.jasperreports.engine.base.JRBaseStyle to field net.sf.jasperreports.engine.base.JRBaseParagraph.paragraphContainer of type net.sf.jasperreports.engine.JRParagraphContainer in instance of net.sf.jasperreports.engine.base.JRBaseParagraph
	java.io.ObjectStreamClass$FieldReflector.setObjFieldValues(ObjectStreamClass.java:2063)
	java.io.ObjectStreamClass.setObjFieldValues(ObjectStreamClass.java:1241)
	java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1995)
	java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913)
	java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
	java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
	java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989)
	java.io.ObjectInputStream.defaultReadObject(ObjectInputStream.java:499)
	net.sf.jasperreports.engine.base.JRBaseStyle.readObject(JRBaseStyle.java:1429)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:601)
	java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1004)
	java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891)
	java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
	java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
	java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989)
	java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913)
	java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
	java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
	java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
	java.util.ArrayList.readObject(ArrayList.java:733)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:601)
	java.io.ObjectStreamClass.invokeReadObject(ObjectStreamClass.java:1004)
	java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1891)
	java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
	java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
	java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989)
	java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913)
	java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
	java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
	java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1989)
	java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1913)
	java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1796)
	java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1348)
	java.io.ObjectInputStream.readObject(ObjectInputStream.java:370)
	net.sf.jasperreports.engine.util.JRLoader.loadObject(JRLoader.java:192)
	org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsView.loadReport(AbstractJasperReportsView.java:516)
	org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsView.loadReport(AbstractJasperReportsView.java:498)
	org.springframework.web.servlet.view.jasperreports.AbstractJasperReportsView.initApplicationContext(AbstractJasperReportsView.java:327)
	org.springframework.context.support.ApplicationObjectSupport.initApplicationContext(ApplicationObjectSupport.java:119)
	org.springframework.web.context.support.WebApplicationObjectSupport.initApplicationContext(WebApplicationObjectSupport.java:69)
	org.springframework.context.support.ApplicationObjectSupport.setApplicationContext(ApplicationObjectSupport.java:73)
	org.springframework.context.support.ApplicationContextAwareProcessor.postProcessBeforeInitialization(ApplicationContextAwareProcessor.java:70)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:350)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1329)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:471)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
	java.security.AccessController.doPrivileged(Native Method)
	org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
	org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
	org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:220)
	org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
	org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
	org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
	org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
	org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
	org.springframework.web.servlet.view.ResourceBundleViewResolver.initFactory(ResourceBundleViewResolver.java:244)
	org.springframework.web.servlet.view.ResourceBundleViewResolver.loadView(ResourceBundleViewResolver.java:186)
	org.springframework.web.servlet.view.AbstractCachingViewResolver.createView(AbstractCachingViewResolver.java:159)
	org.springframework.web.servlet.view.AbstractCachingViewResolver.resolveViewName(AbstractCachingViewResolver.java:78)
	org.springframework.web.servlet.DispatcherServlet.resolveViewName(DispatcherServlet.java:1205)
	org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1154)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:901)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:809)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:571)
	org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:501)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
note La trace complète de la cause mère de cette erreur est disponible dans les fichiers journaux de Apache Tomcat/6.0.36.


Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.