Creating a Simple Reporting Application using JasperReport and iBatis Framework
In this article i’m trying to create a very simple reporting application. In my several past projects, i used to do reporting with java swing and jasper report, and im connecting both of them using a simple JDBC and java.sql.Connection. But in recent project, i had to used iBatis Framework for replacing JDBC. So i had to spend several hours finding a workaround on how connecting Jasper with iBatis, but thanks to uncle Google i finally found a very simple but elegant workaround.
Enough with the chit-chat, i’ll show you the code. First, as always, a simple database named “test” and a simple table named “contoh”.
CREATE DATABASE 'test' USE 'test' CREATE TABLE `contoh` ( `nama` varchar(30) NOT NULL DEFAULT '', `alamat` varchar(100) DEFAULT NULL, PRIMARY KEY (`nama`) )
next step is creating a java bean for database mapping
package com.edw.bean; public class Contoh { private String nama; private String alamat; public String getAlamat() { return alamat; } public void setAlamat(String alamat) { this.alamat = alamat; } public String getNama() { return nama; } public void setNama(String nama) { this.nama = nama; } }
and an xml mapping for database queries, i named it contoh.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE sqlMap PUBLIC "-//ibatis.apache.org//DTD SQL Map 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-2.dtd" > <sqlMap namespace="contoh" > <resultMap id="result" class="com.edw.bean.Contoh"> <result property="nama" column="NAMA" columnIndex="1"/> <result property="alamat" column="ALAMAT" columnIndex="2"/> </resultMap> <insert id="insertContoh" parameterClass="com.edw.bean.Contoh" > insert into contoh (nama, alamat) values (#nama:VARCHAR#, #alamat:VARCHAR#) </insert> <select id="selectAllContoh" resultMap="result"> select nama, alamat from contoh </select> </sqlMap>
and ibatis’ main xml configuration, sqlmapconfig.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE sqlMapConfig PUBLIC "-//ibatis.apache.org//DTD SQL Map Config 2.0//EN" "http://ibatis.apache.org/dtd/sql-map-config-2.dtd"> <sqlMapConfig> <settings useStatementNamespaces="true" lazyLoadingEnabled="true" enhancementEnabled="true" maxSessions="20" /> <transactionManager type="JDBC" commitRequired="false"> <dataSource type="SIMPLE"> <property name="SetAutoCommitAllowed" value="false"/> <property name="DefaultAutoCommit" value="false"/> <property name="JDBC.Driver" value="com.mysql.jdbc.Driver"/> <property name="JDBC.ConnectionURL" value="jdbc:mysql://localhost/test"/> <property name="JDBC.Username" value="root"/> <property name="JDBC.Password" value="password"/> </dataSource> </transactionManager> <sqlMap resource="com/edw/sqlmap/contoh.xml"/> </sqlMapConfig>
next step is creating a simple java class to load all iBatis’ configuration file.
package com.edw.config; import com.ibatis.common.resources.Resources; import com.ibatis.sqlmap.client.SqlMapClient; import com.ibatis.sqlmap.client.SqlMapClientBuilder; import java.io.IOException; import java.io.Reader; /** * * @author edw */ public class SqlMapConfig { protected static final SqlMapClient sqlMap; static { try { Reader reader = Resources.getResourceAsReader("com/edw/sqlmap/sqlmapconfig.xml"); sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader); } catch (IOException e) { throw new RuntimeException("Fatal Error, ga dapet sqlmapconfignya. Cause: " + e, e); } catch (Exception e){ throw new RuntimeException("Fatal Error. Cause: " + e, e); } } public static SqlMapClient getSqlMap() { return sqlMap; } }
I create a very simple reporting using JasperReport, i named it Iseng.jrxml and compile it into Iseng.jasper
<?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="Iseng" pageWidth="595" pageHeight="842" columnWidth="555" leftMargin="20" rightMargin="20" topMargin="20" bottomMargin="20"> <property name="ireport.zoom" value="1.0"/> <property name="ireport.x" value="0"/> <property name="ireport.y" value="0"/> <parameter name="nama1" class="java.lang.String"/> <queryString> <![CDATA[]]> </queryString> <field name="nama" class="java.lang.String"/> <field name="alamat" class="java.lang.String"/> <background> <band splitType="Stretch"/> </background> <title> <band height="56" splitType="Stretch"> <staticText> <reportElement x="0" y="0" width="555" height="46"/> <textElement textAlignment="Center" verticalAlignment="Middle"> <font size="24"/> </textElement> <text><![CDATA[Testing Report]]></text> </staticText> </band> </title> <pageHeader> <band height="13" splitType="Stretch"/> </pageHeader> <columnHeader> <band height="34" splitType="Stretch"> <staticText> <reportElement x="0" y="11" width="100" height="20"/> <textElement textAlignment="Center" verticalAlignment="Middle"/> <text><![CDATA[Nama]]></text> </staticText> <staticText> <reportElement x="225" y="11" width="100" height="20"/> <textElement textAlignment="Center" verticalAlignment="Middle"/> <text><![CDATA[Alamat]]></text> </staticText> </band> </columnHeader> <detail> <band height="27" splitType="Stretch"> <textField> <reportElement x="32" y="0" width="100" height="20"/> <textElement/> <textFieldExpression class="java.lang.String"><![CDATA[$F{nama}]]></textFieldExpression> </textField> <textField> <reportElement x="225" y="0" width="100" height="20"/> <textElement/> <textFieldExpression class="java.lang.String"><![CDATA[$F{alamat}]]></textFieldExpression> </textField> </band> </detail> <columnFooter> <band height="45" splitType="Stretch"/> </columnFooter> <pageFooter> <band height="54" splitType="Stretch"/> </pageFooter> <summary> <band height="42" splitType="Stretch"/> </summary> </jasperReport>
And this is my main Swing class. iBatis generate a List of Beans class for its result set, and im using Jasper’s JRBeanCollectionDataSource class to map iBatis’ resultSet.
package com.edw.ui; import com.edw.bean.Contoh; import com.edw.config.SqlMapConfig; import com.ibatis.sqlmap.client.SqlMapClient; import java.awt.Container; import java.awt.FlowLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.util.HashMap; import java.util.List; import javax.swing.JButton; import javax.swing.JFrame; 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 net.sf.jasperreports.view.JasperViewer; import org.apache.log4j.Logger; /** * * @author edw */ public class Main extends JFrame implements ActionListener { private Logger logger = Logger.getLogger(this.getClass()); private JButton cmdPrint = new JButton("cetak"); private SqlMapClient sqlMapClient = SqlMapConfig.getSqlMap(); public Main() { Container conn = getContentPane(); conn.setLayout(new FlowLayout()); conn.add(cmdPrint); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); cmdPrint.addActionListener(this); pack(); } public void actionPerformed(ActionEvent e) { if (e.getSource() == cmdPrint) { try { //load report location FileInputStream fis = new FileInputStream("Iseng.jasper"); BufferedInputStream bufferedInputStream = new BufferedInputStream(fis); // do query and get list of Contoh List<Contoh> contohs = sqlMapClient.queryForList("contoh.selectAllContoh"); //fill it in JRBeanCollectionDS JRBeanCollectionDataSource jrbcds = new JRBeanCollectionDataSource(contohs); //compile report JasperReport jasperReport = (JasperReport) JRLoader.loadObject(bufferedInputStream); JasperPrint jasperPrint = JasperFillManager.fillReport(jasperReport, new HashMap(), jrbcds); //view report to UI JasperViewer.viewReport(jasperPrint, false); } catch (Exception ex) { logger.error(ex.getMessage(), ex); } } } public static void main(String[] args) { Main main = new Main(); main.setVisible(true); } }
and my log4j configuration, i named it log4j.properties
# Global logging configuration log4j.rootLogger=DEBUG,stdout # Console output... log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d [%c{1}] %-5p %c:%L - %m%n
this is my NetBeans’ project structure,
dont forget to put your .jasper file in the same folder as your build.xml file,
this is what happen when i run my application, on the background you can see iBatis’ resultSet.
and this is what happen when i push my report button
I hope my article can be useful for others, thank you and have fun using iBatis.
(H)