Using The JasperReports Struts2 Plugin, A Main Report, And A Subreport


My next step in learning how to use JasperReports, is to integrate JasperReports into a Struts2 web application. There is a Struts2 JasperReports plugin (refer 1) that is part of the Struts2 download. Look for the jar named "struts2-jasperreports-plugin-" in the struts-\lib directory.

Using the Struts2 JasperReports plugin it's relatively easy to integrate JasperReports into your web application. There are a couple of changes you'll need to make to the master report if you're using a subreport. The changes you need to make are not well documented as it took me several hours of trouble shooting to figure it out. Luckily, Dave Newton, a Struts2 - JasperReports plugin expert, kindly explained to me what I was doing wrong.

I thought it would be a good idea to write the steps up in my blog to help others who are trying to use the Struts2 JasperReports plugin with a main report and subreport.

Example Application

I'm using the example application from reference 2 (see below). You can view a working example and also download a complete war file with all source code (including the .jrxml files).

In the example application there is a Person class that has three attributes (firstName, lastName, and phones). The phones attribute is an ArrayList of Phone objects. The Phone class has two attributes (phoneNumber and phoneType).

In the previous example (refer. 2), I had a main report and a subreport. The subreport was used to display each Person's phone numbers and phone types. I'll be using those same reports for the web application.

I created a dynamic web application in Eclipse and brought in the Person and Phone classes (in package model). I then put all the Struts2 and JasperReport jar files into my web-inf/lib directory. I then created a simple Struts2 ActionSupport class that has an execute method that just returns success. This class also has a getBeanCollection method that returns an ArrayList of Person objects. This method will be used as the data source to fill the Jasper report with data.

Modify The Main JasperReport .jrxml File

The one important step that took me so much trouble to figure out (and thanks again to Dave Newton) is that you have to modify your main .jrxml file if you're using a subreport that is linked to the main report through a field that is an ArrayList (in this case the phones field of class Person).

First copy the struts2-jasperreports-plugin- to the lib folder that is under iReports (in my case this is "C:\Program Files\JasperSoft\iReport-3.0.0\lib"). Then start up iReport.

Open the main report, which in the example is contacts.jrxml. Select View - Fields, and then click on the phones field and click on modify.

Under Field Class Type enter: org.apache.struts2.views.jasperreports.ValueStackDataSource. This is a data type defined by the Struts2 JasperReports plugin. This data type will ensure the Collection type (phones) is exposed to the subreport by the Struts2 JasperReport plugin.

Click OK and close the fields window.

Next, right click on the subreport and select properties. Click on the Subreport tab and change this

new JRBeanCollectionDataSource($F{phones})

(which is under Use data source expression) to this


The Struts2 JasperReport plugin will handle processing the phones ArrayList and make it available to the subreport.

Next click the Subreport (Other) tab and under Subreport Expression enter this:


(this is the location in your web application class path where the subreport can be located, so in my examples the subreport is under web-inf/classes/jasper). Then your web application will be able to find the subreport.

Close that window. Save the report and Build - Compile. Make sure your Options - Settings - Compiler is set to compile the report into the correct folder in your web application (in my example that is WebContent/Jasper).

Also make sure you've compiled the subreport and copied the subreport .jasper file into the correct folder in your web application (again in my example that is web-inf/classes/jasper).

Struts2 XML

In the struts2.xml I defined a package and action with the following code.

<package name="default" extends="jasperreports-default,struts-default">

<action name="myJasperTest" class="action.JasperAction">

        <result name="success" type="jasper">
<param name="location">/jasper/contacts.jasper</param>
<param name="dataSource">beanCollection</param>
<param name="format">PDF</param>

<result name="error" type="jasper">/Error.jsp</result>



Note the extends attribute value of the package node.

In the action's success result the type is set to jasper and three parameter values are passed. The location parameter specifies where to find the main report (in my example the main report is in /jasper/contacts.jasper from my web application's root directory. The dataSource parameter value is the getBeanCollection method (Struts2 calls the getBeanCollection method if you use the beanCollection value) in the ActionSupport class (found in action.JasperAction). This method returns an ArrayList of Person objects that are used to fill the JasperReport.

Lastly, the format parameter specifies the returned report format (eg PDF). Check out the plugin API (reference 1) for other report format types you can specify.


Hopefully, you'll be able to follow these guidelines to get your own Struts2 - JasperReports web application up and running. In the references section are links to the Struts2 mailing list and to the JasperReports forum. Searching those two resources may help you answer any questions.


  1. Struts2 JasperReports Plug In
  2. Bruce Phillips Blog, Using JasperReports With An ArrayList of Objects Part 2: Using the Report In A Java Application
  3. Working Example, Struts2 JasperReports Plug In, Main Report and Subreport
  4. Struts2 Mailing List
  5. JasperReports User Forum
  6. Download a complete war file of the example

Comments (Comment Moderation is enabled. Your comment will not appear until approved.)
To control the name of the result file and to help browsers identify the result return type (eg PDF), you can use the contentDisposition param as follows:

<result name="success" type="jasper">
<param name="location">/jasper/contacts.jasper</param>
<param name="dataSource">beanCollection</param>
<param name="format">PDF</param>
         <param name="contentDisposition">attachment;filename="contacts.pdf"</param>
# Posted By Bruce | 7/16/08 5:45 PM
how to use the label <param name="reportParameters">parametros</param> to pass parameters in struts2?

PLEASEEEEEEE could give me an example?
# Posted By oscar | 7/17/08 7:31 AM
Oscar - Unfortunately I've not used the "reportParameters" in the Struts2 JasperReports plugin. I recommend you post your question on the Struts2 mailing list (see references).
# Posted By Bruce | 7/19/08 6:53 AM
Hi,Bruce Phillips
How are you! I don't download your war file(struts2-jasperreport),please email to me. My Email is you very mach!
# Posted By kevin | 9/8/08 12:19 AM
Kevin - The .war file example is too large to email as an attachment. You can download it from the references.
# Posted By Bruce | 9/8/08 5:07 AM
First, I would like to thank you for the example on jasper reports in struts2. It is very helpful for understanding the JasperReports Struts2 Plugin.
I also need to implement some charts in my application. It would be great if you can provide an example on how to create charts at runtime in an struts2 application.
# Posted By Manish | 10/12/08 11:22 PM
I'm trying to use jasper report + subreport, buy my subreport is in the title band, i pass a java.util.List like a parameter, y named it in jasperreport like you suggest, bu I got the followin error;
java.lang.NoClassDefFoundError: Could not initialize class org.apache.struts2.views.jasperreports.ValueStackDataSource
and I have no idea than waths be wrong.
I using ireport 3.0.0 and jasperreport struts plugin 2.1.2
# Posted By ccl | 10/20/08 12:29 PM
Hi Bill, great note... i have a cuestion in ur example use a BeanCollection for the DataSource, i do the dummy for undersatnd the way it works, and it works.jejej. Well i have a cuestion? have some example for use a Spring Loaded Hibernate Connection, or who cant i use my AppCntx whit a Hibernate Connection on my Struts2 config Xml and.. how i send a map of parameter to mi report to use that parameter in my report.

that's all jeje just a little cuestion xD.. i hope u can help me and Thanx
# Posted By Apolo Rodriguez | 11/27/08 12:27 PM
Hi, Bill: Thank you very much for your paper. I don't know how you make the .jrxml and .jasper files in your sample. I download the .war file and see them already there. Did you make them in iReport? Will please explain it a little more. I read your other paper and wonder if I need to make them in a jave file outside the struts2 first and then use that one in strust2? Thnaks, Qing
# Posted By Qing | 12/7/08 7:54 PM
To pass parameters to the jasper report from the Action class, use :
<param name="reportParameters">${reportParams}</param> for the
jasper result configuration in struts.xml.
reportParams is a regular HashMap in the Action with a getter and setter
( used as reportParams.put("user", getUser()); )
In the .jrxml file , declare a Map parameter called reportParams and use
($P{reportParams}).get("user") to get its value.
# Posted By Sonia Sawlani | 12/8/08 3:15 PM

See: for an introduction to using iReport to create the .jrxml and .jasper files.
# Posted By Bruce | 12/9/08 11:45 AM
Hi, ( sorry, i am not speak english lenguage )
I have a problem and i can not resolve
I using ireport 3.0.0 and jasperreport struts plugin 2.1.2
I'm trying to use jasper report + subreport

When i use "new JRBeanCollectionDataSource($F{myList})" for the data source of subreport the error is :

java.lang.NoClassDefFoundError: Could not initialize class org.apache.struts2.views.jasperreports.ValueStackDataSource
and I have no idea than waths be wrong.

I need help
# Posted By Joaquín Balaguer | 12/22/08 3:39 AM
Hi, Bruce:

Thanks for your help. I got the report as in your paper part1. But when I try it in struts2 (your paper part2), I got the error:
net.sf.jasperreports.engine.fill.JRExpressionEvalException: Error evaluating expression :      Source text : $F{phones} 
Caused by: java.lang.ClassCastException: java.util.ArrayList cannot be cast to org.apache.struts2.views.jasperreports.ValueStackDataSource 
I don't know what's wrong when I follow your instruction for the web application. I made a new DataSource by using action.JasperAction as Factory class. Then use this Datasource to make .jrxml file with subreport through iReport. Then made all the changes for main .jrxml as you mentioned.
Any further help from you shall be highly appreciated.

# Posted By Qing | 12/29/08 1:50 AM
Hi, Bruce:
I had your struts2 example code working. Two problems bothered me for a while:
1. I shouldn't run the struts2 version .jasper in iReport.
2. There is a conflict in jar files which prevent me to start Tomcat (Error filterstart). When deletting xercesImpl.jar, everything is fine. I don't know what will happen without xercesImpl.jar in my project.
Thank you very much for your great examples.
# Posted By Qing | 1/1/09 11:43 AM
Hi, Bruce:
I have a parent report which is consists of three or may be until seven subreport. And I use JRBeanCollectionDataSource to fullfill every subreport where between one and another subreport used different java bean (ie: Person, BankAccount, Department, etc) and also different parameter (I used HashMap as parameter which is have several object's key) .

So, I use this method to fill the subreport :

private void fillSubReport(Collection<PayslipDescription> items,
         HashMap parameter, String subReportName) {
      try {
//subReportName = Payment4_subreport4_subreport2.jasper
         File reportFile = ResourcesHelper.getResourceAsFile(subReportName);
         JasperPrint jasperPrint = JasperFillManager.fillReport(reportFile
               .getAbsolutePath(), parameter,
               new JRBeanCollectionDataSource(items));
      } catch (IOException e) {
      } catch (JRException e) {

But, i'am not sure it can running well, because if several user request or access this report on the same time from different machine with the different parameter, sometimes the report will give the same responds or the same data. How come? with the different parameter it should give different report too.
Do you have any opinion?

Thnx & Regards,
# Posted By vajar | 1/7/09 8:20 PM
Thanks for this forum and sample that were being presented. This help me a lot and save my day.

# Posted By winmac | 1/20/09 9:26 PM
I'm having the same problem as Qing. SEVERE: Servlet.service() for servlet default threw exception
java.lang.ClassCastException: org.apache.struts2.views.jasperreports.ValueStackDataSource cannot be cast to java.util.Map

Any ideas?

# Posted By JimDee | 2/5/09 2:35 PM

What type of collection object are you using for your sub-report. From the error message I suspect it is a collection type that implements the Map interface. I don't think Map type objects will work. My example uses an ArrayList which implements the Collection interface.
# Posted By Bruce | 2/5/09 3:32 PM
Hmm. I didn't notice that Map in the listing. But my getter and setter are using List.
   private List<CommitmentPojo> commitments;
   public List<CommitmentPojo> getCommitments() {
      return commitments;
   public void setCommitments(List<CommitmentPojo> commitments) {
      this.commitments = commitments;

In fact none of my collections are Maps, they are all Lists.

I instantiate the List like this:
List<CommitmentPojo> commitments = new ArrayList<CommitmentPojo>();
Then when this list is populated it is added to another pojo object using the setCommitment method listed above.

So no Maps that I can see.

I wonder if I need to use the ArrayList classinstead of the List Interface?

# Posted By JimDee | 2/5/09 4:00 PM
I started over from scratch and now the error is gone so I must have missed something along the way.

Now, though, the subreport arraylist is now being populated. Any thoughts?
# Posted By JimDee | 2/9/09 10:52 AM
Forget my previous comment. I forgot to change the field class type to ValueStackDataSource. Once I did that everything worked fine.

Next I'm going to try adding a subreport to my subreport because each item in my subreport arraylist has it's own array list of further details.

Thanks for this blog entry. I would never have been able to get this working without it.
# Posted By JimDee | 2/9/09 11:04 AM

any news on that error:
NoClassDefFoundError: Could not initialize class org.apache.struts2.views.jasperreports.ValueStackDataSource
I am using iReport 3.0.0 and im running into the same when trying to create a report. What is strange: When I add the jar to the classpath, iReport complains that some logger from xwork is missing. After adding the xwork related jar, iReport again complains about missing ValueStackDataSource, though both are in the classpath right now.

# Posted By Christian Forster | 2/14/09 8:28 PM
Hi Bruce,

It works fine.

But I am using the Struts 2 - ibatis - MySQL - jasper report combination.

I got the report, But i didnt get the sub report.

Please guide me on this issue
# Posted By Siva NP | 3/10/09 2:20 AM
Bruce, Do you know if this application works in struts 2.1.6, i try to migrate it, and get a blank PDF, anyone know if the new struts 2 release need a special behaivor about jasper?
# Posted By Alex Rios | 3/13/09 4:06 PM
Alex - I don't know if the application works under Struts 2.1.6. Recommend you search through the Struts User group here:
# Posted By Bruce | 3/14/09 8:03 AM
I tried the exampled below, which is mentioned on this page.

I use the version 1.2.1 of jasperreports with the 2.0.14 version of Struts2 and are having trouble with the reportParameters param.
I seems this is not a part of the 1.2.1 version of jasperreports which I use.

Any ideas on how I can pass parameters to my report by using this version of Struts2 and jasperreport?

Thank you very much in advance :)

To pass parameters to the jasper report from the Action class, use :
<param name="reportParameters">${reportParams}</param> for the
jasper result configuration in struts.xml.
reportParams is a regular HashMap in the Action with a getter and setter
( used as reportParams.put("user", getUser()); )
In the .jrxml file , declare a Map parameter called reportParams and use
($P{reportParams}).get("user") to get its value.
# Posted By ALM | 3/27/09 9:32 AM
Hi there
I've been trying desperately to get the report, but not succesful. The error I get is datasource not found...

I have made a simple Action class where I set a List of elements with ibatis. return Success and that's it. The datasource is infoList, which has its getter and setter param. First I populate it with ibatis


and then I return success.

Any help? Thanks a lot.
# Posted By Silvie | 4/21/09 5:48 PM

Can you run the example application that is in part 2 of this series (just a main report example) and then use that application with your List?
# Posted By Bruce | 4/21/09 7:26 PM
Hi Bruce, thanks, I've done it. I just do not understand very well the magic of Stack Value hehehe. But at least i did it. I am getting data from database and showing it in the report. Now, the next problem:

I get the same infoLista from Ibatis (that uses a bean to be filled), but need to manipulate the resultant data. I can do it, the problem is when I try to populate the list with new values to be sent to the report. Any ideas? I've tried with an ArrayList but nothing, if I use setters from the same action they work, but don't iterate over.

public ArrayList getInfoAmortizacion(){
ArrayList listaPzoFijo = new ArrayList();
... make calculus, etc...
setFtasafija(tasaFija); // this work but don't iterate


return listaPzoFijo;
# Posted By Silvie | 4/27/09 1:16 PM
Bruce, thank you so much for writing this down, especially converting Collections to ValueStackDataSource. It's very much appreciated. Cheers, Zoran.
# Posted By Zoran | 6/8/09 2:10 AM
Hi, Bruce

it's a great note.. I've been trying get a report in excel format (XLS) but it's totally empty.. what could be the problem?
# Posted By Jessica | 6/21/09 10:44 PM

There could be several problems - incorrect JRXML, not converting to ValueStack DataSource correctly if you're using a sub-report.

Try to create a very simple example (no sub report and see if you can create a working application that creates an Excel spreadsheet or PDF).

Put some plain text in your .jrxml file to ensure you see something in addition to the dynamic fields bound to the data.

Try working through the first two example applications in parts 1 and 2 of this series.

# Posted By Bruce | 6/22/09 3:14 PM
Hi, Bruce
I downloaded your example application , it works. But when i compile your contacts_subreport0.jrxml br my iReport 3.5.2 and instead of your WEB-INF\classes\jasper\contacts_subreport0.jasper by it, and runed it. the report didn't display subreport(phone_report), i can't understand, please tell me why, thank you very much!
# Posted By Amanda | 10/15/09 4:20 AM
I being testing with new iReport 3.6.1 but exception show!

In 3.0.0 works fine!

Error compiling the report java source!
java.lang.NoClassDefFoundError: net/sf/jasperreports/engine/JRDataSource     at java.lang.ClassLoader.defineClass1(Native Method)     at java.lang.ClassLoader.defineClass(     at     at     at$000(     at$     at Method)     at     at java.lang.ClassLoader.loadClass(     at sun.misc.Launcher$AppClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at org.netbeans.ProxyClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.ClassLoader.loadClassInternal(     at java.lang.Class.forName0(Native Method)     at java.lang.Class.forName(     at net.sf.jasperreports.engine.util.JRClassLoader.loadClassForRealName(     at net.sf.jasperreports.engine.util.JRClassLoader.loadClassForName(     at net.sf.jasperreports.engine.base.JRBaseField.getValueClass(     at     at     at     at     at     at     at     at org.openide.util.RequestProcessor$     at org.openide.util.RequestProcessor$ Caused by: java.lang.ClassNotFoundException: net.sf.jasperreports.engine.JRDataSource     at$     at Method)     at     at java.lang.ClassLoader.loadClass(     at sun.misc.Launcher$AppClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.ClassLoader.loadClassInternal(     ... 31 more
Compilation running time: 313
# Posted By Vinicius Pádua | 11/20/09 3:08 PM
Hi Bruce,
I know this way is a bit inappropriate and probably you still get a headache(I'll be glad to supply you with some quality drugs :) ) when someone asks you over and over a same question, but I've no other options but to ask you
I'm following your example for using iReport(my version 3.7.2) and Struts2(plugin same as yours) but I run into problem when I try to compile main report from iReport (I get this exception) for $F{answers} set as datasource for subreport :
Error filling print... Error evaluating expression :      Source text : $F{answers}
net.sf.jasperreports.engine.fill.JRExpressionEvalException: Error evaluating expression :      Source text : $F{answers}

java.lang.ClassCastException: java.util.ArrayList cannot be cast to org.apache.struts2.views.jasperreports.ValueStackDataSource.

My Beans are Questionnaire and Answer. Questionnaire has List<Answer>.

a static method from factory class:
      public static List<Questionnaire> getBeans(){
      List <Questionnaire> records = new ArrayList<Questionnaire>();
      Questionnaire q = new Questionnaire();
      q.setCreatedate(new Date());


      List<Answer> answers = new ArrayList<Answer>();
      for(int i = 0; i<5; i++){
         Answer a = new Answer();
         a.setText("odgovor je "+i);
         a.setDateAnswer(new Date());
      return records;

What I'm doing wrong?
Many thanks

# Posted By Predrag Popovi? | 8/29/10 5:24 PM
Hey Bruce,

I am running with the below exception. I followed a similar solved post(by Qing), but it dint save me.

java.util.ArrayList cannot be cast to org.apache.struts2.views.jasperreports.ValueStackDataSource

Any help is oxygen to me now.

# Posted By Vinay | 9/29/10 4:54 AM
About java.lang.NoClassDefFoundError: Could not initialize class org.apache.struts2.views.jasperreports.ValueStackDataSource

Copy struts2-jasperreports-plugin- in the lib directory then add it to iReport classpath (Tools > Options > iReport > Classpath > Add JAR)
# Posted By Monica | 1/18/11 4:46 AM
It seems that I am having similar problems mentioned before. When trying to compile your sample jrxml files, I get the following exception -

Error compiling the report java source!
java.lang.NoClassDefFoundError: net/sf/jasperreports/engine/JRDataSource     at java.lang.ClassLoader.defineClass1(Native Method)     at java.lang.ClassLoader.defineClassCond(     at java.lang.ClassLoader.defineClass(     at     at
Caused by: java.lang.ClassNotFoundException: net.sf.jasperreports.engine.JRDataSource     at$     at Method)     at

This seems odd, considering JRDataSource should be in the core jasperreports-4.0.1.jar (yeah, using the latest and greatest, maybe this is my mistake). I have manually added this jar to my classpath, but this solved nothing.

There is no doubt that this error is caused by the following:

   <field name="openEndData" class="org.apache.struts2.views.jasperreports.ValueStackDataSource">

I have added the struts2 jar to the classpath as well, and have added the struts plugin for good measure. Neither of which seem to be doing much in this case.

Any ideas?

Great post, by the way
# Posted By Dan | 4/18/11 2:05 PM
It worked for me, thanks a lot Bruce. and i want to convert report file to doc, how can i do it ? when i mention <param name="format">doc</param> in struts.xml it shows unknown format, do i required any other jars ? any way i am trying to do that, if you know the solution please let me know..

Thanks for your useful examples.

# Posted By Arun | 3/5/12 7:31 AM
Arun - check out:

I think there is a new Struts 2 plugin you can use to create a MS Word document.
# Posted By Bruce | 3/5/12 9:24 AM
Im using jasper report 5.1.0 and follow your instruction carefully but i encounter this error:

java.lang.NoClassDefFoundError: net/sf/jasperreports/engine/JRRewindableDataSource     at java.lang.ClassLoader.defineClass1(Native Method)     at java.lang.ClassLoader.defineClass(     at     at     at$100(     at$     at$     at Method)     at     at java.lang.ClassLoader.loadClass(     at sun.misc.Launcher$AppClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at org.netbeans.ProxyClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.ClassLoader.loadClass(     at java.lang.Class.forName0(Native Method)     at java.lang.Class.forName(

thanks for your blog.. Please help me

thank you
# Posted By veztre | 5/2/13 9:56 PM
BlogCFC was created by Raymond Camden. This blog is running version Contact Blog Owner