Struts 2 and Jasper Subreports Integration Example


This example shows you how to integrate the Jasper Subreports with Struts 2 application to generate the dynamic reports. Jasper Subreport functionality helps to manage the large report in an easy way by dividing into subreports.

Tools used in this article:

  1. Eclipse IDE
  2. JDK 8
  3. Maven
  4. MySQL
  5. iReports
  6. Tomcat 8

Initialize the HashMap<String, Object> and put the all the parameters details.

Map<String, Object> parameterMap = new HashMap<>();
parameterMap.put("SUBREPORT_DIR", JasperCompileManager.compileReport(path + "/Subreport.jrxml"));
parameterMap.put("EmpResultSet", new JRResultSetDataSource(rs));

Compile the master report and fill the report by calling JasperFillManager.fillReport(JasperReport jasperReport, Map<String, Object> parameters, JRDataSource dataSource). Pass the empty datasource to the master report.

JasperReport jr = JasperCompileManager.compileReport(path + "/Report.jrxml");
JasperPrint jp = JasperFillManager.fillReport(jr, parameterMap, new JREmptyDataSource(1));

Export the report by calling JasperExportManager.exportReportToPdfFile(JasperPrint jasperPrint, String destFileName).

JasperExportManager.exportReportToPdfFile(jp, path + "EmployeeRecords" + ".pdf");

Note: You can send as many ResultSets as you want in the parameters map but make sure to declare the parameters in the report with the same names and set the parameter class as net.sf.jasperreports.engine.JRResultSetDataSource.

Dependencies Required

To work with Struts 2 and JasperReport, you must have included the core JAR. To resolve the JAR dependency, you add the following dependency on your pom.xml.

pom.xml
<dependencies>
    <dependency>
        <groupId>org.apache.struts</groupId>
        <artifactId>struts2-core</artifactId>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>5.1.17</version>
    </dependency>
    <dependency>
        <groupId>net.sf.jasperreports</groupId>
        <artifactId>jasperreports</artifactId>
        <version>5.6.0</version>
    </dependency>
</dependencies>

Project Structure in Eclipse

Have a look of project structure in Eclipse IDE.

Struts 2 and Jasper Subreports Integration Example

Table Creation

Create the EMP_DETAILS table and inserts some values using MySQL database. Find the table script.

emp_details.sql
CREATE TABLE `emp_details` (
  `ename` varchar(40) DEFAULT NULL,
  `designation` varchar(20) DEFAULT NULL,
  `dept` varchar(30) DEFAULT NULL,
  `salary` mediumtext,
  `location` varchar(30) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Design the Report

To design your report you can use the iReports tool. You need to design the two separate reports first is master reports and second is subreport and link the subreport into the master reports. Find the jrxml of both reports.

Report.jrxml
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Report" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20" uuid="826a3b83-7937-4ac8-85d5-f9c83ade7de2">
    <property name="ireport.zoom" value="1.0"/>
    <property name="ireport.x" value="0"/>
    <property name="ireport.y" value="0"/>
    <parameter name="EmpResultSet" class="net.sf.jasperreports.engine.JRResultSetDataSource"/>
    <parameter name="SUBREPORT_DIR" class="net.sf.jasperreports.engine.JasperReport"/>
    <parameter name="NODATA" class="java.lang.String"/>
    <title>
        <band height="116" splitType="Stretch">
            <staticText>
                <reportElement mode="Opaque" x="2" y="74" width="553" height="27" uuid="53cf9fd0-95be-4ca9-bb7e-408f185625c2"/>
                <textElement textAlignment="Center">
                    <font size="14" isBold="true"/>
                </textElement>
                <text><![CDATA[Struts 2 and Jasper Subreports Integration Example]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="2" y="0" width="553" height="66" isPrintWhenDetailOverflows="true" forecolor="#1F77B4" backcolor="#FFFFFF" uuid="bbf86b85-6975-45b7-9751-6387e4502bbd"/>
                <textElement textAlignment="Center" verticalAlignment="Middle">
                    <font fontName="Lato Black" size="36" isBold="true"/>
                </textElement>
                <text><![CDATA[WebSparrow.org]]></text>
            </staticText>
        </band>
    </title>
    <detail>
        <band height="19" splitType="Stretch">
            <subreport>
                <reportElement positionType="Float" x="2" y="0" width="555" height="19" isPrintWhenDetailOverflows="true" uuid="0d90bb22-f5dc-47ac-98b4-97e1d319af44"/>
                <dataSourceExpression><![CDATA[$P{EmpResultSet}]]></dataSourceExpression>
                <subreportExpression><![CDATA[$P{SUBREPORT_DIR}]]></subreportExpression>
            </subreport>
        </band>
        <band height="31">
            <textField isBlankWhenNull="true">
                <reportElement x="0" y="0" width="555" height="31" forecolor="#FF6666" uuid="bd35ac07-569c-4e5b-a491-939c4fe2e302"/>
                <textElement textAlignment="Center" verticalAlignment="Middle">
                    <font fontName="Arial Narrow" size="14"/>
                </textElement>
                <textFieldExpression><![CDATA[$P{NODATA}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

In the subreport fields, names must be the same as stored in ResultSet.

Subreport.jrxml
<?xml version="1.0" encoding="UTF-8"?>
<jasperReport xmlns="http://jasperreports.sourceforge.net/jasperreports" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://jasperreports.sourceforge.net/jasperreports http://jasperreports.sourceforge.net/xsd/jasperreport.xsd" name="Subreport" pageWidth="555" pageHeight="802" columnWidth="555" leftMargin="0" rightMargin="0" topMargin="0" bottomMargin="0" uuid="50db5a0c-f527-42ce-8efe-1b546b1c672e">
    <property name="ireport.zoom" value="1.0"/>
    <property name="ireport.x" value="0"/>
    <property name="ireport.y" value="0"/>
    <field name="ename" class="java.lang.String"/>
    <field name="designation" class="java.lang.String"/>
    <field name="dept" class="java.lang.String"/>
    <field name="salary" class="java.lang.Double"/>
    <field name="location" class="java.lang.String"/>
    <background>
        <band splitType="Stretch"/>
    </background>
    <columnHeader>
        <band height="45" splitType="Stretch">
            <staticText>
                <reportElement x="153" y="3" width="241" height="20" uuid="056c13dc-cac4-4f7e-8a1c-317a2cdbc0ae"/>
                <textElement textAlignment="Center">
                    <font size="12" isBold="true"/>
                </textElement>
                <text><![CDATA[Employee Details]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="40" y="25" width="97" height="20" backcolor="#EAFAFA" uuid="d3606189-cf6c-4c4f-958e-92a44ada6bcb"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center">
                    <font size="10" isBold="true"/>
                </textElement>
                <text><![CDATA[Name]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="137" y="25" width="97" height="20" backcolor="#EAFAFA" uuid="d6d6729a-eb68-451d-9cc9-fa19a2040383"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center">
                    <font size="10" isBold="true"/>
                </textElement>
                <text><![CDATA[Designation]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="234" y="25" width="97" height="20" backcolor="#EAFAFA" uuid="96852632-98ae-4a7e-a894-d679ae0373cd"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center">
                    <font size="10" isBold="true"/>
                </textElement>
                <text><![CDATA[Department]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="331" y="25" width="97" height="20" backcolor="#EAFAFA" uuid="9f00a551-63cc-4e36-a7a1-0b271a24ff8b"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center">
                    <font size="10" isBold="true"/>
                </textElement>
                <text><![CDATA[Salary]]></text>
            </staticText>
            <staticText>
                <reportElement mode="Opaque" x="428" y="25" width="97" height="20" backcolor="#EAFAFA" uuid="475a005a-d420-4799-8308-d7dd99babf42"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center">
                    <font size="10" isBold="true"/>
                </textElement>
                <text><![CDATA[Location]]></text>
            </staticText>
        </band>
    </columnHeader>
    <detail>
        <band height="20" splitType="Stretch">
            <textField>
                <reportElement x="40" y="0" width="97" height="20" uuid="f5d03d17-7404-4cfe-afac-f9b5bacb8087"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center" verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{ename}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="137" y="0" width="97" height="20" uuid="fe34bb14-f6bd-45bc-a2ef-cce89d0aff49"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center" verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{designation}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="234" y="0" width="97" height="20" uuid="3e685ba5-77a0-41f0-a04c-25b08dbee35d"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center" verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{dept}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="331" y="0" width="97" height="20" uuid="e5246887-9c88-4e86-865a-42bec3516a76"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center" verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{salary}]]></textFieldExpression>
            </textField>
            <textField>
                <reportElement x="428" y="0" width="97" height="20" uuid="957c0911-fd8e-41bd-b447-ce74f9846321"/>
                <box>
                    <topPen lineWidth="0.25"/>
                    <leftPen lineWidth="0.25"/>
                    <bottomPen lineWidth="0.25"/>
                    <rightPen lineWidth="0.25"/>
                </box>
                <textElement textAlignment="Center" verticalAlignment="Middle"/>
                <textFieldExpression><![CDATA[$F{location}]]></textFieldExpression>
            </textField>
        </band>
    </detail>
</jasperReport>

Struts 2 Filter

Define the Struts 2 filter in web.xml file.

web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	id="WebApp_ID" version="2.5">
	<display-name>Struts2AndJasperSubReport</display-name>
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>
	<filter>
		<filter-name>struts2</filter-name>
		<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>struts2</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
</web-app>

DAO Class

Create the Data Access Object class to fetch the employee details from the table.

SubReportDao.java
package org.websparrow;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

public class SubReportDao {

	public static ResultSet employeeDetails() {
		ResultSet rs = null;
		try {
			Class.forName("com.mysql.jdbc.Driver");
			Connection con = DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/websparrow", "root", "");
			PreparedStatement ps = con.prepareStatement("SELECT ename,designation,dept,salary,location FROM emp_details");
			rs = ps.executeQuery();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return rs;
	}
}

Action Class

Inside the Action class initialize the HashMap<String, Object> and put the subreport and data source of subreport in the form of ResultSet.

SubReportAction.java
package org.websparrow;

import java.io.File;
import java.io.FileInputStream;
import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;

import net.sf.jasperreports.engine.JREmptyDataSource;
import net.sf.jasperreports.engine.JRResultSetDataSource;
import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;

public class SubReportAction extends ActionSupport {
	private static final long serialVersionUID = 3275286583598504231L;
	private String isSelected;
	private ResultSet rs;
	private FileInputStream fileInputStream;

	@Override
	public String execute() throws Exception {
		try {

			String path = ServletActionContext.getServletContext().getRealPath("/assets");
			Map<String, Object> parameterMap = new HashMap<>();

			if (isSelected.equalsIgnoreCase("YES")) {
				
				rs = SubReportDao.employeeDetails();
				parameterMap.put("SUBREPORT_DIR", JasperCompileManager.compileReport(path + "/Subreport.jrxml"));
				parameterMap.put("EmpResultSet", new JRResultSetDataSource(rs));

			} else {
				parameterMap.put("NODATA", "Please select YES from 'Show Employees Details' boxce .");
			}

			JasperReport jr = JasperCompileManager.compileReport(path + "/Report.jrxml");
			JasperPrint jp = JasperFillManager.fillReport(jr, parameterMap, new JREmptyDataSource(1));
			JasperExportManager.exportReportToPdfFile(jp, path + "EmployeeRecords" + ".pdf");
			fileInputStream = new FileInputStream(new File(path + "EmployeeRecords" + ".pdf"));

		} catch (Exception e) {
			e.printStackTrace();
		}
		return SUCCESS;
	}

	public String getIsSelected() {
		return isSelected;
	}

	public void setIsSelected(String isSelected) {
		this.isSelected = isSelected;
	}

	public FileInputStream getFileInputStream() {
		return fileInputStream;
	}

	public void setFileInputStream(FileInputStream fileInputStream) {
		this.fileInputStream = fileInputStream;
	}
}

UI Component

Create the JSP page for the user interface.

index.jsp
<%@taglib prefix="s" uri="/struts-tags"%>
<html>
<head>
<title>Struts 2 and Jasper Subreports Integration Example</title>
</head>
<body>
	<h1>Struts 2 and Jasper Subreports Integration Example</h1>
	<s:form action="SubReport" method="POST">
		<s:select label="Show Employees Details" list="#{'YES':'YES', 'NO':'NO'}" name="isSelected" />
		<s:submit value="Submit" />
	</s:form>
</body>
</html>

Map Action Class

Finally, map the action class inside the struts.xml and set the result type=stream.

struts.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
	<constant name="struts.devMode" value="true" />
	<package name="default" extends="struts-default" namespace="/">
		<action name="SubReport" class="org.websparrow.SubReportAction">
			<result name="success" type="stream">
				<param name="contentType">application/octet-stream</param>
				<param name="inputName">fileInputStream</param>
				<param name="contentDisposition">attachment;filename="EmployeeRecords.pdf"</param>
				<param name="bufferSize">1024</param>
			</result>
		</action>
	</package>
</struts> 
Output:

Now everything is all set. Deploy the project inside the Tomcat » webapps folder and start the server.

URL: localhost:8090/Struts2AndJasperSubReport/

If we select YES from then it will include the subreport in the main report and display all employees details and if we select NO then it will not include the employee’s details in the main report. See the below screenshot for more details.

Struts 2 and Jasper Subreports Integration Example

Similar Posts

About the Author

Atul Rai
I love sharing my experiments and ideas with everyone by writing articles on the latest technological trends. Read all published posts by Atul Rai.