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:
- Eclipse IDE
- JDK 8
- Maven
- MySQL
- iReports
- 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 asnet.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.
<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.
Table Creation
Create the EMP_DETAILS
table and inserts some values using MySQL database. Find the table script.
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.
<?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
.
<?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.
<?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.
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
.
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.
<%@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
<?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>
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.
Download Source Code: struts2-and-jasper-subreports-integration-example.zip