Yet Another Simple Swing, Spring and Ibatis Integration Example

I was working on my side project while drinking a cup of (C) when suddenly i had an idea, why cant i rely on Spring’s Transaction instead of Ibatis’ plain transaction. I see that Spring’s Transaction with annotation is much much simpler than Ibatis’ old fashioned transaction with try-catch and commit-rollback method. Okay, enough with the chit-chat. Let me show you the code.

First, i create a very simple database, with one table consist of 2 simple columns.

USE 'test'

CREATE TABLE 'contoh' (
  'nama' varchar(30) NOT NULL,
  '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 "-// SQL Map 2.0//EN" 
"" >
<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"/>

    <insert id="insertContoh" parameterClass="com.edw.bean.Contoh" >
    insert into contoh (nama, alamat)
    values (#nama:VARCHAR#, #alamat:VARCHAR#)

    <select id="selectAllContoh" resultMap="result">
    select nama, alamat
    from contoh


and ibatis’ main xml configuration, sqlmapconfig.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sqlMapConfig
PUBLIC "-// SQL Map Config 2.0//EN"



    <sqlMap resource="com/edw/sqlmap/contoh.xml"/>


because im using Spring, i need one main xml configuration for my Spring app, i named it spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=""

    <context:component-scan base-package="com.edw"/>
    <tx:annotation-driven transaction-manager="transactionManager"/>

    <bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
        <property name="configLocation" value="com/edw/sqlmap/sqlmapconfig.xml"/>
        <property name="dataSource" ref="dataSource"/>

    <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost/test"/>
        <property name="username" value="root"/>
        <property name="password" value="password"/>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>


and 1 singleton class to load my configuration,

package com.edw.config;

 * @author edw
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;

public class ApplicationContextProvider {

    private Logger logger = Logger.getLogger(ApplicationContextProvider.class);
    private ApplicationContext applicationContext;
    private static final ApplicationContextProvider provider = new ApplicationContextProvider();

    private ApplicationContextProvider() throws ExceptionInInitializerError {
        try {
            this.applicationContext = new ClassPathXmlApplicationContext("spring.xml");
        } catch (Throwable ex) {
            logger.error("Initial ApplicationContext creation failed -- " + ex.getMessage(), ex);
            throw new ExceptionInInitializerError(ex);

    public synchronized static ApplicationContextProvider getInstance() throws ExceptionInInitializerError {
        return provider;

    public ApplicationContext getApplicationContext() {
        return applicationContext;

    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;

i create a DAO class, to connect to my ibatis layer,

package com.edw.dao;

import com.edw.bean.Contoh;
import com.ibatis.sqlmap.client.SqlMapClient;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Repository;

 * @author edw
@Repository(value = "contohDao")
public class ContohDao extends SqlMapClientDaoSupport {

    // empty constructor
    public ContohDao() {       
    // autowired constructor
    // i dont know why, but i cant autowired sqlMapClient directly
    // it will cause  java.lang.IllegalArgumentException: Property 'sqlMapClient' is required
    public ContohDao(SqlMapClient sqlMapClient) {

    public void insert(Contoh contoh){

    public List<Contoh> select(){
        return getSqlMapClientTemplate().queryForList("contoh.selectAllContoh");

and my Service class, i use it to connect to my DAO layer,

package com.edw.service;

import com.edw.bean.Contoh;
import com.edw.dao.ContohDao;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

 * @author edw
public class ContohService  {

    private ContohDao contohDao;
    private Logger logger = Logger.getLogger(ContohService.class);

    public void insert(Contoh contoh) {
        logger.debug("begin insert at "+this.getClass().getName());
        logger.debug("end insert at "+this.getClass().getName());

    public List<Contoh> select() {
        logger.debug("begin select at "+this.getClass().getName());
        List<Contoh> contohs =;
        logger.debug("end select at "+this.getClass().getName());
        return contohs;

please be careful with isolation level, from what i’ve read,

In a typical application, multiple transactions run concurrently, often working
with the same data to get their job done. Concurrency, while necessary, can lead
to the following problems:

  • Dirty read—Dirty reads occur when one transaction reads data that has been
    written but not yet committed by another transaction. If the changes are
    later rolled back, the data obtained by the first transaction will be invalid.
  • Nonrepeatable read—Nonrepeatable reads happen when a transaction performs
    the same query two or more times and each time the data is different.
    This is usually due to another concurrent transaction updating the data
    between the queries.
  • Phantom reads—Phantom reads are similar to nonrepeatable reads. These
    occur when a transaction (T1) reads several rows, and then a concurrent
    transaction (T2) inserts rows. Upon subsequent queries, the first transaction
    (T1) finds additional rows that were not there before.

That’s why, im using Isolation.SERIALIZABLE, because

This fully ACID-compliant isolation level ensures that dirty
reads, nonrepeatable reads, and phantom reads are all
prevented. This is the slowest of all isolation levels
because it is typically accomplished by doing full table
locks on the tables involved in the transaction.

this is my UI

package com.edw.ui;

import com.edw.bean.Contoh;
import com.edw.config.ApplicationContextProvider;
import com.edw.service.ContohService;
import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;

 * @author edw
public class MenuUtama extends JFrame implements ActionListener {

    private JTextField txtNama = new JTextField();
    private JTextField txtAlamat = new JTextField();
    private JButton cmdButton = new JButton("Save");
    private Logger logger = Logger.getLogger(MenuUtama.class);

    public MenuUtama() {
        setLayout(new GridLayout(3, 3));
        Container con = this.getContentPane();
        con.add(new JLabel("nama : "));
        con.add(new JLabel("Alamat : "));


    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == cmdButton) {
            Contoh contoh = new Contoh();

            try {
                ApplicationContext ac = ApplicationContextProvider.getInstance().getApplicationContext();
                ContohService service = (ContohService) ac.getBean("contohService");
            } catch (Exception ex) {
                logger.error(ex.getMessage(), ex);

    public static void main(String[] args) {
        MenuUtama menuUtama = new MenuUtama();
        menuUtama.setSize(300, 150);

this is my junit test case

package com.edw.test;

import com.edw.bean.Contoh;
import com.edw.config.ApplicationContextProvider;
import com.edw.service.ContohService;
import java.util.List;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.springframework.context.ApplicationContext;

 * @author edw
public class TestKoneksi {

    public void testingMain(){

        Logger logger = Logger.getLogger(TestKoneksi.class);

        ApplicationContext ac = ApplicationContextProvider.getInstance().getApplicationContext();
        ContohService service = (ContohService)ac.getBean("contohService");
        List<Contoh> contohs =;

        for (Contoh contoh : contohs) {
            logger.debug(contoh.getNama()+" - "+contoh.getAlamat());

        Contoh contoh = new Contoh();


this is the appereance of my swing app
ibatis swing spring app

this is what written on my console

[SqlMapClientTemplate] DEBUG org.springframework.orm.ibatis.SqlMapClientTemplate:177 - Opened SqlMapSession [com.ibatis.sqlmap.engine.impl.SqlMapSessionImpl@b05acd] for iBATIS operation
[Connection] DEBUG java.sql.Connection:27 - {conn-100000} Connection
[SqlMapClientTemplate] DEBUG org.springframework.orm.ibatis.SqlMapClientTemplate:194 - Obtained JDBC Connection [com.mysql.jdbc.JDBC4Connection@17ec9f7] for iBATIS operation
[Connection] DEBUG java.sql.Connection:27 - {conn-100000} Preparing Statement:      insert into contoh (nama, alamat)     values (?, ?)     
[PreparedStatement] DEBUG java.sql.PreparedStatement:27 - {pstm-100001} Executing Statement:      insert into contoh (nama, alamat)     values (?, ?)     
[PreparedStatement] DEBUG java.sql.PreparedStatement:27 - {pstm-100001} Parameters: [ibatisInsert, testing masuk Ibatis]
[PreparedStatement] DEBUG java.sql.PreparedStatement:27 - {pstm-100001} Types: [java.lang.String, java.lang.String]
[ContohService] DEBUG com.edw.service.ContohService:28 - end insert at com.edw.service.ContohService
[DataSourceTransactionManager] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:730 - Initiating transaction commit
[DataSourceTransactionManager] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:259 - Committing JDBC transaction on Connection [com.mysql.jdbc.JDBC4Connection@17ec9f7]
[DataSourceUtils] DEBUG org.springframework.jdbc.datasource.DataSourceUtils:193 - Resetting isolation level of JDBC Connection [com.mysql.jdbc.JDBC4Connection@17ec9f7] to 4
[DataSourceTransactionManager] DEBUG org.springframework.jdbc.datasource.DataSourceTransactionManager:314 - Releasing JDBC Connection [com.mysql.jdbc.JDBC4Connection@17ec9f7] after transaction
[DataSourceUtils] DEBUG org.springframework.jdbc.datasource.DataSourceUtils:312 - Returning JDBC Connection to DataSource
[MenuUtama] DEBUG com.edw.ui.MenuUtama:51 - success

my NB Project Structure and libraries that i used
Netbeans Project structure, libraries and stuffs

btw, i highly recommend these books to understand more about Spring and Ibatis framework.

  1. Manning Spring in Action 2nd Edition
  2. Manning Ibatis in Action

thank you, have fun and good luck.

How to Convert Java List or ArrayList into ResultSet

At this project i found an obstacle, which i need to convert a reporting module from fetching data from database into fetching data from Webservices. At first I think it was easy, I just fetch strings from Webservice, and put it in a bean or in a map and put it all in an ArrayList, just like JasperReport. But I forgot, this isn’t JasperReport I’m using, I’m using bloody hell CrystalReport. And my Crystal-Report-calling method only accepting ResultSet for parameter, so somehow I need to convert strings from webservice into ResultSet.

My idea is adding strings from webservices into an ArrayList<Object> and adding this ArrayList into ArrayList<ArrayList<Object>> and converting it into rows of ResultSet. And im using MockRunner library to help me. This is how I do it :

I create a class to convert a list into result set


import com.mockrunner.mock.jdbc.MockResultSet;
import java.sql.ResultSet;
import java.util.List;

 * @author edw
public class MyResultSet {

    public ResultSet getResultSet(List<String> headers, List<List<Object>> data) throws Exception {

        // validation
        if (headers == null || data == null) {
            throw new Exception("null parameters");

        if (headers.size() != data.size()) {
            throw new Exception("parameters size are not equals");

        // create a mock result set
        MockResultSet mockResultSet = new MockResultSet("myResultSet");

        // add header
        for (String string : headers) {          

        // add data
        for (List<Object> list : data) {

        return mockResultSet;

and i tested it with my junit class


import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.junit.Test;

 * @author edw
public class MyResultSetTest {

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

    public MyResultSetTest() {

    public void testMyResultSet() throws Exception {
        MyResultSet myResultSet = new MyResultSet();
        List<String> headers = new ArrayList<String>();

        List<List<Object>> data = new ArrayList<List<Object>>();
        for (int i = 0; i < 4; i++) {
            List<Object> objects = new ArrayList<Object>();
            objects.add(new Integer(i));
            objects.add("name " + i);
            objects.add(new Double(i));
            objects.add(new Integer(20 + i));

        ResultSet rs = myResultSet.getResultSet(headers, data);
        while ( {


this is the result on my IDE console

2010-08-18 18:13:09,112 [MyResultSetTest] DEBUG - 0
2010-08-18 18:13:09,131 [MyResultSetTest] DEBUG - name 0
2010-08-18 18:13:09,132 [MyResultSetTest] DEBUG - 0.0
2010-08-18 18:13:09,132 [MyResultSetTest] DEBUG - 20
2010-08-18 18:13:09,133 [MyResultSetTest] DEBUG - ------------------------
2010-08-18 18:13:09,133 [MyResultSetTest] DEBUG - 1
2010-08-18 18:13:09,189 [MyResultSetTest] DEBUG - name 1
2010-08-18 18:13:09,189 [MyResultSetTest] DEBUG - 1.0
2010-08-18 18:13:09,189 [MyResultSetTest] DEBUG - 21
2010-08-18 18:13:09,190 [MyResultSetTest] DEBUG - ------------------------
2010-08-18 18:13:09,190 [MyResultSetTest] DEBUG - 2
2010-08-18 18:13:09,191 [MyResultSetTest] DEBUG - name 2
2010-08-18 18:13:09,218 [MyResultSetTest] DEBUG - 2.0
2010-08-18 18:13:09,219 [MyResultSetTest] DEBUG - 22
2010-08-18 18:13:09,219 [MyResultSetTest] DEBUG - ------------------------
2010-08-18 18:13:09,219 [MyResultSetTest] DEBUG - 3
2010-08-18 18:13:09,220 [MyResultSetTest] DEBUG - name 3
2010-08-18 18:13:09,225 [MyResultSetTest] DEBUG - 3.0
2010-08-18 18:13:09,226 [MyResultSetTest] DEBUG - 23
2010-08-18 18:13:09,226 [MyResultSetTest] DEBUG - ------------------------

this is my project structure, FYI im using Netbeans 6.9.
Netbeans 6.9 Project Structure

all i can say is, Thank You mockrunner, you saved my life.

DotA’s Castle Fight Game Mode

from what i’ve read here, Castle Fight’s gamemode need to be entered by player 1 in the first 20 seconds of gametime before round 1 starts.
It has lots of gamemodes, while my favorite is

-rr2 -ntb -nt -nafk -balance -slb -ur -fow -ca -ban -skip

-rr2 = Random races with new races each round with 2 win limit
-ntb = You can’t build Treasure Boxes when this modification has been chosen.
-nt = You don’t have to pay taxes on your income when No Taxes is chosen.
-nafk = Players can’t use the “-afk” command and the AI will also not take control over an afk player after some time.
-balance = Activates auto team balance.
-slb = Units can only move / fly over one lane. -sl picks a random lane while -slt picks the top lane and -slb the bottom lane
-ur = A race can be chosen only once per round (even across the teams).
-fow = There will be Fog of War at the beginning of each round for X seconds. If you just write -fow without a number, you will have indefinite fog of war.
-ca = You are able to block units by building buildings around them in this gamemode. You can use this to build farms like in earlier versions
-ban = Before races get picked/randomed the leader of each team bans X races which cannot be picked/randomed then
-skip = Write this during the first 20 seconds to start round1 immediately (if you have already chosen gamemodes and can’t wait )

Have Fun playing it. 😉

Anything for A Good Picture

ada yang sampe nungging, jongkok dan segala jenis posisi, cekidot gaaan.

ini posisi nungging

zoom sampe mentok

posisi jongkok

ini buah apa yg dipoto??

models : asung, ir dan gw sendiri.

I Love the Blue of Sawarna

Sawarna, this place is about 280 km south from jakarta, around 7 hours in a normal traffic to get there. Excellent beaches, Excellent people, Excellent scenery. And believe me, it’s worth the trip.