Creating Web Based Reports using Jasper Report
It’s easy to export reports to PDF if you do it in desktop application, but what if you had to do it in a web-based application? Here im trying to demonstrate on how to use servlets to generate a pdf based reports, using JasperReport libraries of course.
First, as always, a simple postgresql table,
on database “test”, schema “test”.
DROP TABLE master;
CREATE
TABLE test.master
(
nama CHARACTER VARYING(30) NOT NULL,
usia SMALLINT,
CONSTRAINT idnama PRIMARY KEY (nama)
)
Next step is a very simple jrxml file, i named it reportTest.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="reportTest" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20">
<field name="nama" class="java.lang.String"/>
<field name="usia" class="java.lang.Short"/>
<background>
<band splitType="Stretch"/>
</background>
<title>
<band height="31" splitType="Stretch">
<staticText>
<reportElement x="0" y="0" width="555" height="31"/>
<textElement textAlignment="Center" verticalAlignment="Middle">
<font size="24" isBold="true"/>
</textElement>
<text><![CDATA[Test Report Page]]></text>
</staticText>
</band>
</title>
<pageHeader>
<band height="11" splitType="Stretch"/>
</pageHeader>
<columnHeader>
<band height="8" splitType="Stretch"/>
</columnHeader>
<detail>
<band height="25" splitType="Stretch">
<textField>
<reportElement x="19" y="0" width="100" height="20"/>
<textElement textAlignment="Center"/>
<textFieldExpression class="java.lang.String"><![CDATA[$F{nama}]]></textFieldExpression>
</textField>
<textField>
<reportElement x="168" y="0" width="100" height="20"/>
<textElement/>
<textFieldExpression class="java.lang.Short"><![CDATA[$F{usia}]]></textFieldExpression>
</textField>
</band>
</detail>
<columnFooter>
<band height="20" splitType="Stretch">
<textField pattern="dd MMMMM yyyy">
<reportElement x="455" y="0" width="100" height="20"/>
<textElement textAlignment="Right"/>
<textFieldExpression class="java.util.Date"><![CDATA[new java.util.Date()]]></textFieldExpression>
</textField>
</band>
</columnFooter>
<pageFooter>
<band splitType="Stretch"/>
</pageFooter>
<summary>
<band height="6" splitType="Stretch"/>
</summary>
</jasperReport>
Im using Hibernate as my ORM library, thats why i need a java bean and a hbm.xml file,
package com.edw.report.bean;
public class Master implements java.io.Serializable {
private String nama;
private Short usia;
public Master() {
}
// other setters and getters
@Override
public String toString() {
return "Master{" + "nama=" + nama + " usia=" + usia + '}';
}
}
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class name="com.edw.report.bean.Master" table="master" schema="test">
<id name="nama" type="string">
<column name="nama" length="30" />
<generator class="assigned" />
</id>
<property name="usia" type="java.lang.Short">
<column name="usia" />
</property>
</class>
</hibernate-mapping>
And this is my main hibernate configuration file, hibernate.cfg.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</property>
<property name="hibernate.connection.driver_class">org.postgresql.Driver</property>
<property name="hibernate.connection.url">jdbc:postgresql://localhost:5432/test</property>
<property name="hibernate.connection.username">postgres</property>
<property name="hibernate.connection.password">password</property>
<mapping resource="com/edw/report/bean/Master.hbm.xml"/>
</session-factory>
</hibernate-configuration>
And a factory class to load my hibernate configuration file, it’s actually by default load hibernate.cfg.xml file.
package com.edw.report.util;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
/**
* Hibernate Utility class with a convenient method to get Session Factory object.
*
* @author edw
*/
public class HibernateUtil {
private static final SessionFactory sessionFactory;
static {
try {
sessionFactory = new AnnotationConfiguration().configure().buildSessionFactory();
} catch (Throwable ex) {
System.err.println("Initial SessionFactory creation failed." + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
return sessionFactory;
}
}
And finally, my servlet class. It use Jasper Report libraries, and export my report to PDF by changing its header to application/pdf instead of text/html. Take a look at line 53, class FileInputStream load my reportTest.jasper file that located under WEB-INF folder.
package com.edw.report.servlet;
import com.edw.report.bean.Master;
import com.edw.report.util.HibernateUtil;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import net.sf.jasperreports.engine.JasperExportManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.engine.data.JRBeanCollectionDataSource;
import net.sf.jasperreports.engine.util.JRLoader;
import org.apache.log4j.Logger;
import org.hibernate.Session;
/**
*
* @author edw
*/
public class ReportServlet extends HttpServlet {
private Logger logger = Logger.getLogger(ReportServlet.class);
protected void processRequest(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
// set header as pdf
response.setContentType("application/pdf");
// set input and output stream
ServletOutputStream servletOutputStream = response.getOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileInputStream fis;
BufferedInputStream bufferedInputStream;
try {
// get report location
ServletContext context = getServletContext();
String reportLocation = context.getRealPath("WEB-INF");
// get report
fis = new FileInputStream(reportLocation + "/reportTest.jasper");
bufferedInputStream = new BufferedInputStream(fis);
// fetch data from database
Session session = HibernateUtil.getSessionFactory().openSession();
List<Master> masters = (List<Master>) session.createCriteria(Master.class).list();
session.close();
// log it
for (Master master : masters) {
logger.debug(master.toString());
}
// fill it
JRBeanCollectionDataSource jrbcds = new JRBeanCollectionDataSource(masters);
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(bufferedInputStream);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap(), jrbcds);
// export to pdf
JasperExportManager.exportReportToPdfStream(jasperPrint, baos);
response.setContentLength(baos.size());
baos.writeTo(servletOutputStream);
// close it
fis.close();
bufferedInputStream.close();
} catch (Exception ex) {
logger.error(ex.getMessage(), ex);
} finally {
servletOutputStream.flush();
servletOutputStream.close();
baos.close();
}
}
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);
}
@Override
public String getServletInfo() {
return "Reporting Servlet";
}
}
Dont forget to register your servlet to web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<servlet>
<servlet-name>ReportServlet</servlet-name>
<servlet-class>com.edw.report.servlet.ReportServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ReportServlet</servlet-name>
<url-pattern>/ReportServlet</url-pattern>
</servlet-mapping>
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>
</web-app>
Here is my Netbeans’ project screenshoot




Btw if you are using Struts 1, it will be easier. All you have to do is create an Action class to handle all the reporting, and register it to struts-config.xml. Here is my example.
package com.edw.action;
public class ReportAction extends org.apache.struts.action.Action {
private static final String SUCCESS = "success";
private Logger logger = Logger.getLogger(ReportAction.class);
@Override
public ActionForward execute(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
ServletContext context = getServlet().getServletContext();
String reportLocation = context.getRealPath("WEB-INF");
List<Log> logs = logService.select();
FileInputStream fis = new FileInputStream(reportLocation+"/report.jasper");
BufferedInputStream bufferedInputStream = new BufferedInputStream(fis);
ServletOutputStream servletOutputStream = response.getOutputStream();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Map<String, String> map = new HashMap<String, String>();
JRBeanCollectionDataSource jrbcds = new JRBeanCollectionDataSource(logs);
JasperReport jasperReport = (JasperReport) JRLoader.loadObject(bufferedInputStream);
JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, map, jrbcds);
response.setContentType("application/pdf");
JasperExportManager.exportReportToPdfStream(jasperPrint, baos);
response.setContentLength(baos.size());
baos.writeTo(servletOutputStream);
// close all
fis.close();
bufferedInputStream.close();
servletOutputStream.flush();
servletOutputStream.close();
return mapping.findForward(SUCCESS);
}
}
dont forget to put your Action class on your struts-config.xml
<action path="/report" type="com.edw.action.ReportAction"/>
Hope this can help others, have fun. (*)










