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. (*)

Google+

28 Comments

ZeeXiang

about 6 years ago

Hi Edwin, Great Job!!! Thank you for sharing, It's much more easier by using struts. Btw, how can I set the report into a frame instead of whole web page? I am currently using struts-tiles for my project. How can I rate you? Thanks, Zee Xiang

Reply

edwin

about 5 years ago

Hi ZeeXiang, yes you could display report from iFrame, with a little bit effort of course. create an iframe with a name and in your form just set action target to iframe's name.

vikas

about 5 years ago

Hello Sir, Thnx for such nice and illustrative solution.Sir I want to integrate jasper Reports in jsp and servlets only as i am using same in my project .kindly give me source code for the same.I am a novice and needed it badly . Thnx in advance . :-(

Reply

edwin

about 5 years ago

Hi vikas, displaying jasper report within jsp is almost the same like using servlet. :)

Boonyasak Kaewpriwan

about 5 years ago

Excellent working !!! .. Thank you ,I implement jasper reporting on Aviarc framework I think it's the same Hipernate concept that working for me.

Reply

Boonyasak Kaewpriwan

about 5 years ago

(Y) Excellent working !!! .. Thank you ,I implement jasper reporting on Aviarc framework I think it's the same Hipernate concept that working for me.

Reply

edwin

about 5 years ago

Hi Boonyasak Kaewpriwan, glad that it could help you :)

yacine

about 5 years ago

thank you great job

Reply

yacine

about 5 years ago

hi I wonder if we can send a resultset retrieve a function directly in a report without being'm writing in the Requet jasperreport thanks

Reply

edwin

about 5 years ago

hi yacine, yes you can. You could use jasperreport's class, JRBeanCollectionDataSource or JRmapCollectionDataSource You could see the example here or here

FAROOQ

about 5 years ago

am getting an error : File does not begin with '%PDF-'. can u tell me were am going wrong ?

Reply

edwin

about 5 years ago

Hi FAROOQ, could you share your complete stacktrace?

Partha

about 5 years ago

Hi, This is a nice article. I prefer Struts. BTW, I am not used to Hibernate. Can I avoid Hibernate ? If so, any instructions please? Also, is it difficult to learn Hibernate ? Thanks Partha

Reply

edwin

about 5 years ago

Hi Partha, Despite in my article i use Hibernate, you could use other frameworks or even simple plain jdbc to display your reports :)

Do Hang

about 5 years ago

Hi Edwin. I am a new in jasper. Now I am using Struts but I can not perform your code in my PC. My web is not understand ServletContext, FileInputStream,BufferedInputStream.... Please help me. Thanks

Reply

edwin

about 5 years ago

Hi Do Hang, you can import those classes from your sourcecode.

Hussain

about 5 years ago

Hi Edwin, Thanks for very good illustrative post. I have followed all the steps you have listed. But i could not see the generated pdf report. It just shows grey screen on the eclipse browser. Even i don't get any error when i run ReportServlet or JasperWebReporting project. I'm using Eclipse Indigo. Please guide me to get this working. Thanks!!!

Reply

edwin

about 5 years ago

Hi Hussain, perhaps it's because your eclipse browser doesnt have pdf plugins. Try opening your page from google chrome or mozilla instead. :)

ram

about 5 years ago

what about the jsp file???

Reply

edwin

about 5 years ago

Hi Ram, Are you asking about how to run report viewer on jsp? Well you can modified the servlet version and fit it into jsp, dont forget to give pdf header to the jsp.

yuvi

about 3 years ago

Hey Edwin, I started creating web project in eclipse, then I used Netbeans but I am getting error, like java.lang.NoClassDefFoundError: Could not initialize class net.sf.jasperreports.engine.util.JRStyledTextParser while exporting to PDF also it says unable to read font. Am I missing any library? please help.

Reply

edwin

about 3 years ago

Hi Yuvi, are you moving your project to a different operating system? some linux variant doesnt have the font needed by jasper report, so you need to install them manually.

piyush kumar

about 3 years ago

hi edwin, I am trying to use this but since I dont know hibernate, I am not getting it completely executing. So can you just post the code without hibernate. And I also did not get the file report.jasper in your explanation. So please help me here(I am completely new to reporting tools ).

Reply

edwin

about 3 years ago

Hi Piyush, you can use simple JDBC for replacing hibernate.

bluv

about 1 year ago

Hi Edwin, Could I get the source code ? Thank you

Reply

edwin

about 1 year ago

well, you can find my sourcecode on this blog ;)

Peter

about 1 month ago

Do it support a web viewer like crystal reports, instead of a pdf?

Reply

edwin

about 2 weeks ago

hi Peter, cant answer, never used crystal report web viewer before.

Leave a Comment

Please be polite. We appreciate that.
Your email address will not be published and required fields are marked


:-[ (B) (^) (P) (@) (O) (D) :-S ;-( (C) (&) :-$ (E) (~) (K) (I) (L) (8) :-O (T) (G) (F) :-( (H) :-) (*) :-D (N) (Y) :-P (U) (W) ;-)