edwin Posts

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;
    TABLE test.master
        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"/>
		<band splitType="Stretch"/>
		<band height="31" splitType="Stretch">
				<reportElement x="0" y="0" width="555" height="31"/>
				<textElement textAlignment="Center" verticalAlignment="Middle">
					<font size="24" isBold="true"/>
				<text><![CDATA[Test Report Page]]></text>
		<band height="11" splitType="Stretch"/>
		<band height="8" splitType="Stretch"/>
		<band height="25" splitType="Stretch">
				<reportElement x="19" y="0" width="100" height="20"/>
				<textElement textAlignment="Center"/>
				<textFieldExpression class="java.lang.String"><![CDATA[$F{nama}]]></textFieldExpression>
				<reportElement x="168" y="0" width="100" height="20"/>
				<textFieldExpression class="java.lang.Short"><![CDATA[$F{usia}]]></textFieldExpression>
		<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>
		<band splitType="Stretch"/>
		<band height="6" splitType="Stretch"/>

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

    public String toString() {
        return "Master{" + "nama=" + nama + " usia=" + usia + '}';
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"

    <class name="com.edw.report.bean.Master" table="master" schema="test">
        <id name="nama" type="string">
            <column name="nama" length="30" />
            <generator class="assigned" />
        <property name="usia" type="java.lang.Short">
            <column name="usia" />

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">
    <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"/>

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

        // 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();

            // log it
            for (Master master : masters) {

            // 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);


            // close it

        } catch (Exception ex) {
            logger.error(ex.getMessage(), ex);
        } finally {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);

    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">

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);

    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);

        JasperExportManager.exportReportToPdfStream(jasperPrint, baos);


        // close all


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

How to Handle Jasper Report’s CompilationFailedException

I always use JasperReport for my java projects, but sometimes i found some weird java.lang.NoClassDefFoundError: org/codehaus/groovy/control/CompilationFailedException when im trying to get reports from jasper files. This is my full stack trace exception.

Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError: org/codehaus/groovy/control/CompilationFailedException
        at java.lang.Class.getDeclaredConstructors0(Native Method)
        at java.lang.Class.privateGetDeclaredConstructors(Class.java:2389)
        at java.lang.Class.getConstructor0(Class.java:2699)
        at java.lang.Class.newInstance0(Class.java:326)
        at java.lang.Class.newInstance(Class.java:308)
        at net.sf.jasperreports.engine.JasperCompileManager.getCompiler(JasperCompileManager.java:472)
        at net.sf.jasperreports.engine.JasperCompileManager.loadEvaluator(JasperCompileManager.java:238)
        at net.sf.jasperreports.engine.fill.JRFillDataset.createCalculator(JRFillDataset.java:416)
        at net.sf.jasperreports.engine.fill.JRBaseFiller.<init>(JRBaseFiller.java:408)
        at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:74)
        at net.sf.jasperreports.engine.fill.JRVerticalFiller.<init>(JRVerticalFiller.java:56)
        at net.sf.jasperreports.engine.fill.JRFiller.createFiller(JRFiller.java:143)
        at net.sf.jasperreports.engine.fill.JRFiller.fillReport(JRFiller.java:79)
        at net.sf.jasperreports.engine.JasperFillManager.fillReport(JasperFillManager.java:624)

Actually it happens because im still using Groovy as my report language, instead of Java. All i have to do is change reporting language to java, as you can see below.

Or adding groovy*.jar to your project’s classpath.

Have fun, cheers. (B)

Set MySQL Connection TimeOut

Sometimes you find a condition where your database connection (MySQL) is time out because of your queries are spending too much time. This is a hint on how you increase your MySQL time out configuration.

First you query your default connection timeout.

SHOW VARIABLES LIKE 'connect_timeout';

As you can see below, i have approximately 10 seconds before my mysql connection time out.

Next is updated it to 60 seconds.

SET GLOBAL connect_timeout=60;

Simple isn’t it. 😉

How to Play MP3 Files with Java

Well, it’s actually very simple, first of all you need to download libraries (mp3spi1.9.4.jar, jl1.0.jar and tritonus_share.jar) from Tritonus and from JLayer.

Here is how i code it,

package com.edw.mp3.main;

import java.io.File;
import java.io.IOException;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import org.apache.log4j.Logger;

public class Main extends Thread {

    private String filename;
    private static Logger logger = Logger.getLogger(Main.class);

    public Main(String filename) {
        this.filename = filename;

    public void run() {
        try {
            File file = new File(filename);

            AudioInputStream in = AudioSystem.getAudioInputStream(file);
            AudioInputStream din = null;
            AudioFormat baseFormat = in.getFormat();
            AudioFormat decodedFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED,
                    baseFormat.getChannels() * 2,
            din = AudioSystem.getAudioInputStream(decodedFormat, in);

            // play it...
            rawplay(decodedFormat, din);

        } catch (Exception e) {
        } finally{
            logger.debug("finish playing "+filename);

    private synchronized void rawplay(AudioFormat targetFormat, AudioInputStream din) throws IOException, LineUnavailableException {
        byte[] data = new byte[4096];
        SourceDataLine line = getLine(targetFormat);
        if (line != null) {
            // Start
            int nBytesRead = 0, nBytesWritten = 0;
            while (nBytesRead != -1) {
                nBytesRead = din.read(data, 0, data.length);
                if (nBytesRead != -1) {
                    nBytesWritten = line.write(data, 0, nBytesRead);

            // Stop


    private synchronized SourceDataLine getLine(AudioFormat audioFormat) throws LineUnavailableException {
        SourceDataLine res = null;
        DataLine.Info info =
                new DataLine.Info(SourceDataLine.class, audioFormat);
        res = (SourceDataLine) AudioSystem.getLine(info);

        return res;

    public static void main(String[] args) {
        // my relative path file name
        String song = "Bondan ft. Fade2Black-Ya Sudahlah.mp3";
        logger.debug("start playing "+song);
        Main mp3Sound = new Main(song);

And my Netbeans’ project structure

Actually i code it a long time ago, Thank God it’s still works. If you have any suggestion, feel free to comment it.
Cheers.. (B)

Beginning MyBatis 3

MyBatis framework is a complete rewrite of iBatis, it’s a data mapper framework that makes it easier to use a relational database with object-oriented applications. The difference from old iBatis is that now everything can now be written in java, from queries, configuration to mappers.

Some people might ask why MyBatis use a different approach from its ancestor, iBatis? iBatis’ code generator use *DAOs while MyBatis use *Mappers. I think they all the same, but then according to Clinton Begin they are, despite their similarity, are not exact in concepts.

DAOs can collect multiple statements and thus aggregate or cohesive data logic into one method. That said, this isn’t necessarily a good thing. After 10 years of writing DAOs, I can say with enough experience that DAOs are a waste of time. They fragment business logic, they’re extra code and the abstraction goes largely unused for the lifetime of most applications that implement it. DAOs were often implemented incorrectly and code would sneak into them that should not.

Mappers on the other hand, are named function that executes a single SQL statement or procedure. There is no extra code, and it eliminates strings in the execution of mapped statements. Mappers also help define the mapped statement.

In a sense, you can also think of it as:

  • DAOs USE mapped statements.
  • Mapper methods ARE mapped statements.

The cohesive grouping or aggregation of related statements that work together to form a business process should now exist in your service layer (be it a Spring bean, or an EJB or a POJO service layer).

Okay enough with the chit-chat, let me show you the code, first as always, a simple mysql database named test, and a table named Contoh.

    nama VARCHAR(30) NOT NULL,
    alamat VARCHAR(100),
    PRIMARY KEY (nama)

and a java bean

package com.edw.mybatis.bean;

public class Contoh {
    private String nama;
    private String alamat;

    // other setter and getter

    public String toString(){
        return nama+" : "+alamat;

This is my Contoh table queries, i named it ContohMapper.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.edw.mybatis.mapper.ContohMapper" >
  <resultMap id="ContohMap" type="com.edw.mybatis.bean.Contoh" >
    <id column="nama" property="nama" jdbcType="VARCHAR" />
    <result column="alamat" property="alamat" jdbcType="VARCHAR" />

  <insert id="save" parameterType="com.edw.mybatis.bean.Contoh" >
    insert into contoh (nama, alamat)
    values (#{nama,jdbcType=VARCHAR}, #{alamat,jdbcType=VARCHAR})

  <update id="update" parameterType="com.edw.mybatis.bean.Contoh" >
    update contoh
    set alamat = #{alamat,jdbcType=VARCHAR}
    where nama = #{nama,jdbcType=VARCHAR}


I register my ContohMapper.xml on Configuration.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="UNPOOLED">
                <property name="driver" value="com.mysql.jdbc.Driver"/>
                <property name="url" value="jdbc:mysql://localhost/test"/>
                <property name="username" value="root"/>
                <property name="password" value="xxx"/>
        <mapper resource="com/edw/mybatis/xml/ContohMapper.xml"/>

What makes MyBatis different from iBatis, is the ability to put queries on interfaces using annotations. Here is the example.

package com.edw.mybatis.mapper;

import com.edw.mybatis.bean.Contoh;
import java.util.List;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Select;

public interface ContohMapper {    
    int save(Contoh contoh);

    @Delete("DELETE FROM contoh WHERE nama = #{nama}")
    int delete(String nama);

    @Select("SELECT * FROM contoh WHERE nama = #{nama}")
    Contoh select(String nama);

    @Select("SELECT * FROM contoh")
    List<Contoh> selectAll();

and a factory class to load my configuration

package com.edw.mybatis.config;

import java.io.Reader;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

 * @author edw
public class MyBatisSqlSessionFactory {

    protected static final SqlSessionFactory FACTORY;

    static {
        try {
            Reader reader = Resources.getResourceAsReader("com/edw/mybatis/xml/Configuration.xml");
            FACTORY = new SqlSessionFactoryBuilder().build(reader);
        } catch (Exception e){
            throw new RuntimeException("Fatal Error.  Cause: " + e, e);

    public static SqlSessionFactory getSqlSessionFactory() {
        return FACTORY;

And here’s my main class

package com.edw.mybatis.main;

import com.edw.mybatis.bean.Contoh;
import com.edw.mybatis.config.MyBatisSqlSessionFactory;
import com.edw.mybatis.mapper.ContohMapper;
import java.util.List;
import org.apache.ibatis.session.SqlSession;
import org.apache.log4j.Logger;

public class Main {

    private Logger logger = Logger.getLogger(Main.class);

    public Main() {

    private void execute() {
        SqlSession session = MyBatisSqlSessionFactory.getSqlSessionFactory().openSession();
        try {
            // select all
            ContohMapper mapper = session.getMapper(ContohMapper.class);
            List<Contoh> contohs = mapper.selectAll();
            for (Contoh contoh1 : contohs) {

            // delete
            int success = mapper.delete("pepe");
            if (success == 0) {
                logger.debug("failed to delete");
            } else {
                logger.debug("successfully deleted");

            // insert
            Contoh contohExample = new Contoh();
            contohExample.setAlamat("kacrut alamat");
            int insertSuccess = session.insert("save", contohExample);
            if (insertSuccess == 0) {
                logger.debug("failed to insert");
            } else {
                logger.debug("successfully inserted");

            // check is it inserted yet
            Contoh contoh = (Contoh) mapper.select(contohExample.getNama());

            // update
            Contoh contohExample2 = new Contoh();
            contohExample2.setAlamat("kacrut alamat 22");
            int updateSuccess = session.update("com.edw.mybatis.mapper.ContohMapper.update", contohExample2);
            if (updateSuccess == 0) {
                logger.debug("failed to update");
            } else {
                logger.debug("successfully updated");

        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        } finally {

    public static void main(String[] args) {
        Main main = new Main();

this is what happen when i run my project,

2010-11-12 15:40:41,804 - DEBUG java.sql.Connection:27 - ooo Connection Opened
2010-11-12 15:40:42,041 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT * FROM contoh 
2010-11-12 15:40:42,041 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: 
2010-11-12 15:40:42,100 - DEBUG java.sql.ResultSet:27 - <==    Columns: nama, alamat
2010-11-12 15:40:42,101 - DEBUG java.sql.ResultSet:27 - <==        Row: edwin, singapore
2010-11-12 15:40:42,103 - DEBUG java.sql.ResultSet:27 - <==        Row: kamplenk, ciledug
2010-11-12 15:40:42,104 - DEBUG java.sql.ResultSet:27 - <==        Row: nugie, pamulang
2010-11-12 15:40:42,105 - DEBUG java.sql.ResultSet:27 - <==        Row: samsu, dago
2010-11-12 15:40:42,120 - DEBUG java.sql.ResultSet:27 - <==        Row: tebek, jayapura
2010-11-12 15:40:42,122 - DEBUG com.edw.mybatis.main.Main:24 - edwin : singapore
2010-11-12 15:40:42,122 - DEBUG com.edw.mybatis.main.Main:24 - kamplenk : ciledug
2010-11-12 15:40:42,123 - DEBUG com.edw.mybatis.main.Main:24 - nugie : pamulang
2010-11-12 15:40:42,123 - DEBUG com.edw.mybatis.main.Main:24 - samsu : dago
2010-11-12 15:40:42,123 - DEBUG com.edw.mybatis.main.Main:24 - tebek : jayapura
2010-11-12 15:40:42,133 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: DELETE FROM contoh WHERE nama = ? 
2010-11-12 15:40:42,134 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: pepe(String)
2010-11-12 15:40:42,136 - DEBUG com.edw.mybatis.main.Main:30 - failed to delete
2010-11-12 15:40:42,137 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: insert into contoh (nama, alamat) values (?, ?) 
2010-11-12 15:40:42,138 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: kacrut(String), kacrut alamat(String)
2010-11-12 15:40:42,159 - DEBUG com.edw.mybatis.main.Main:43 - successfully inserted
2010-11-12 15:40:42,160 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: SELECT * FROM contoh WHERE nama = ? 
2010-11-12 15:40:42,160 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: kacrut(String)
2010-11-12 15:40:42,163 - DEBUG java.sql.ResultSet:27 - <==    Columns: nama, alamat
2010-11-12 15:40:42,163 - DEBUG java.sql.ResultSet:27 - <==        Row: kacrut, kacrut alamat
2010-11-12 15:40:42,164 - DEBUG com.edw.mybatis.main.Main:48 - kacrut : kacrut alamat
2010-11-12 15:40:42,166 - DEBUG java.sql.PreparedStatement:27 - ==>  Executing: update contoh set alamat = ? where nama = ? 
2010-11-12 15:40:42,166 - DEBUG java.sql.PreparedStatement:27 - ==> Parameters: kacrut alamat 22(String), kacrut(String)
2010-11-12 15:40:42,202 - DEBUG com.edw.mybatis.main.Main:58 - successfully updated
2010-11-12 15:40:42,259 - DEBUG java.sql.Connection:27 - xxx Connection Closed
BUILD SUCCESSFUL (total time: 2 seconds)

this is my Netbeans 6.9 project structure

Again, another great framework that i’ll obviously use. Cheers, :-[

i almost forget, here is my log4j.properties.

# Global logging configuration

# Console output...
log4j.appender.stdout.layout.ConversionPattern=%d - %-5p %c:%L - %m%n