When utilizing the iBATIS framework you define your SQL Maps to perform the basic CRUD functionality and additional business logic for an individual item. Very often you will be only updating single objects at a time and this is great, but what happens on those occasions where you find yourself processing hundreds of objects at the same time. The simple answer Batch Processing.

Batch Processing is the execution of a set of SQL statements without any user intervention. In essence it takes a group of commands executes them one at a time and then returns the updated count. Well in most cases some drivers won’t return the actual update count and instead returns 0.

Below is a short tutorial on how to perform Batch Processing in Java utilizing the Spring and iBATIS frameworks. In the example we will define and implement the method processInBatch method that will handle the processing. It assumes you have basic knowledge of each of the frameworks and focuses strictly on how to setup batch processing.

Initial Setup

Lets start by assuming for this example that we have a table in our database called APPLICATION and have defined the following basic SQL MAP which has been shortened for brevity.

<?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="Application">
 
	<!-- applicationMap - Application Object Map  -->
	<resultMap id="applicationMap" class="com.example.model.Application" groupBy="id">
		<result property="appId" column="APP_ID" />
		<result property="name" column="NAME" />
		...
	</resultMap>
 
	<!-- list -->
	<select id="Application.list" resultMap="applicationMap" >
		...
	</select>
 
	<!-- insert -->
	<insert id="Application.insert" parameterClass="com.example.model.Application">
		...
	</insert>
 
	<!-- update -->
	<update id="Application.update" parameterClass="com.example.model.Application">
		...
	</update>
 
	<!-- delete -->
	<delete id="Application.delete" parameterClass="com.example.model.Application">
		...
	</delete>
 
</sqlMap>

In addition to created the SQLMap we’ve also create our basic DAO interface ApplicationDAO and implementation ApplicationDAOImpl which extends Spring’s SqlMapClientDaoSupport class.

package com.example.dao;
 
import java.util.List;
import com.example.model.Application;
 
public interface ApplicationDAO {
 
	List<Application> list();
 
	int update( Application obj );
 
	Integer insert( Application obj );
 
	int delete( Application obj );
 
}
package com.example.dao.impl;
 
import java.util.List;
import org.springframework.orm.ibatis.support.SqlMapClientDaoSupport;
 
import com.example.dao.ApplicationDAO;
import com.example.model.Application;
 
public class ApplicationDAOImpl extends SqlMapClientDaoSupport implements ApplicationDAO {
 
	@SuppressWarnings("unchecked")
	public List<Application> list(){
		return (List<Application>) getSqlMapClientTemplate().queryForList( "Application.list" );
	}
 
	public Integer insert( Application obj ){
		Integer result = Integer.valueOf(-1);
		try {
			result = (Integer) getSqlMapClientTemplate().insert( "Application.insert", obj );
		} catch ( Exception e ) {
			log.error( "Failed to insert Application: " + e.getMessage() );
		}
		return result;
	}
 
	public int update( Application obj ){
		return getSqlMapClientTemplate().update( "Application.update", obj );
	}	
 
	public int delete( Application obj ){
		return getSqlMapClientTemplate().delete( "Application.delete", obj );
	}
 
}

Define the new processInBatch method

The processInBatch method will be responsible for setting up and executing the batch. It will take a list of Applications that are to be updated and perform the update SQL Map operation for each of them. To begin lets define the method stub in the ApplicationDAO interface and ApplicationDAOImpl class

// ApplicationDAO
int processInBatch( List<Application> applications );
// ApplicationDAOImpl
public int processInBatch( List<Application> applications ) {
 
}

Understanding the Batch Logic

To perform Batch Processing it is important to understand the two main classes that you will be interacting with SqlMapClientCallback and SqlMapExecutor

The SqlMapClientCallback class

The SqlMapClientCallback is a class to be overwritten in line that will perform the actual batch process. In it you define the doInSqlMapClient method. The SqlMapClientCallback object creates and passes the SqlMapExecutor instance to this method for your usage in setting up and executing the batch. The doInSqlMapClient method like the rest of the methods returns an Object so you can return any object you want.

try {
    Integer updateCount = (Integer) getSqlMapClientTemplate().execute( new SqlMapClientCallback() {
        public Object doInSqlMapClient( SqlMapExecutor executor ) throws SQLException {
 
        }
    });
    return updateCount.intVal();
catch (Exception e ) {
    return -1;
}

Looking at the above base implementation you can see that the general setup is the same for any batch processing you will need to perform the only difference is how you define the doInSqlMapClient method.

Implementing the doInSqlMapClient

The main batch worker is the SqlMapExecutor object. This object has 2 additional methods in addition to the basic insert, update, and execute: startBatch and executeBatch. The startBatch method is used to specify that you are performing the following statements as a batch, instead of executing them in line. Once you have set all your statements the executeBatch method is used to execute all of the statements in a batch and return the update count.

In our example as we are updating all the Applications passed to the processInBatch method we will start the batch, iterate over all applications, for each application call update on the executor for that object, then execute the batch.

executor.startBatch();
Iterator<Application> iter = applications.iterator();
while( iter.hasNext() ) {
    executor.update( "Application.update", iter.next() );
}
return new Integer( executor.executeBatch() );

The complete processInBatch method

public int processInBatch( List<Application> applications ) {
    try {
        Integer updateCount = (Integer) getSqlMapClientTemplate().execute( new SqlMapClientCallback() {
            public Object doInSqlMapClient( SqlMapExecutor executor ) throws SQLException {
                executor.startBatch();
                Iterator<Application> iter = applications.iterator();
                while( iter.hasNext() ) {
                    executor.update( "Application.update", iter.next() );
                }
                return new Integer( executor.executeBatch() );	
            }
        });
        return updateCount.intVal();
    catch (Exception e ) {
        return -1;
    }
}

Wrapping it all Up

There you have it we’ve created a method that executes multiple SQL statements as a batch. This reduces the overhead of performing multiple statements individually and can increase the performance of your applications especially as you get to large sets of statements. The greatest thing is that you don’t need to define any new sql statements and can use the ones you’ve already defined for doing single modifications.

, , , , , , , , ,

One of the main maintenance issues with running a Java application from a shell script is keeping your classpath up-to-date with the new and updated jars. To make things more difficult you can’t specify a folder as the classpath as it doesn’t include the jars in it only .class files. However through the use of a basic for loop we are able to dynamically generate the classpath.

CP=
for i in `ls ./lib/*.jar`
do
  CP=${CP}:${i}
done
, , , , , ,

Have you ever stumbled across a project and just think to yourself why does this class exist, or more specifically why did they use this design pattern? Recently I happened across one of those projects, in it the project used a Factory class that’s purpose was to instantiate and return a single class. In essence the developers knew what the Factory pattern was and utilized it without having any purpose to do so. Instead they created additional worthless code. This use of a programming pattern without the need of the pattern is known as Cargo Cult Programming

Cargo Cult Programming

The Cargo Cult Programming anti-pattern is the use of patterns, structures, or code in a project because you either always do or simply because you don’t know what it is doing but are copying it from another project or programmer. This style of programming causes unnecessary abstraction, code bloat and increases the difficulty of maintaining the project over its life span.

Want to be a better programmer? Then understand your code, don’t blindly copy/paste or use a pattern just because you can. Take your time and think is this needed, does it provide a useful functionality or enhancement to my project? or does it simply add additional code and size to the project. Don’t fall pray to becoming a Cargo Cult Programmer

Resources

, , , ,

Over the lifespan of a software’s code source you will inevitably have to rename functions and properties of classes and maybe even remove them all together. This is not a major issue on simple projects but when your project is used by multiple applications then you may find that you need to keep these deprecated functions until other projects update their code to the new values. The Javadoc deprecated tag is how you mark a function or property as no longer in use and link to the new property or function to use.

The Deprecated Tag

The deprecated tag marks the current property or function as no longer in use. To use the tag simply add it into your Javadoc comments on its own line proceeded by the @ symbol.

/**
 * VIEW - ACTION TYPE
 * @deprecated 
 */
public static final String VIEW = "View";

The Link Tag

When you mark a property or function as deprecated it is always a good idea to link to the new property or function by use of the link tag. You can link to a property/value in the current class or to a property/value in another class.

Link in the current class

/**
 * VIEW - ACTION TYPE
 * @deprecated replaced by {@link #ACTION_VIEW}
 */
public static final String VIEW = "view";

Link in another class

/**
 * filters valid records
 * @deprecated replaced by {@link com.test.TestClass#filter()}
 */

Resources

, , ,

When working in applications that utilize a lot of variables I often come across interfaces containing nothing but constants. Instead of creating a class containing the constants the developers choose to define them in an interface that can be implemented by a class so that constants don’t need to be qualified to a class in the code. This is so widespread that it has been termed the Constant Interface Antipattern. To ease users into correctly defining and using interfaces Java introduced Static Import in version 1.5.

To help illustrate why people choose to use interfaces to define constants lets have a look at an example. Lets assume we have defined our constants in the following interface MyConstants.

public interface MyConstants {
    public static final String PASS= "pass";
    public static final String FAIL = "fail";
}

To use the constants one would have their class implement the interface:

public class BadConstants implements MyConstants {
    private void outputResults() {
        System.out.println("FAIL Constant is " + FAIL);
        System.out.println("PASS Constant is " + PASS);
    }
}

As can be seen in the example the reason people prefer to use this method is that they do not have to qualify the constant by instead using:

System.out.println("FAIL Constant is " + MyConstants.FAIL);

To make it easier for coders to write good code Java introduced the Static Import feature in 1.5. What this does is allow us developers to import static properties into the current class’s namespace effectively allowing you to not qualify the constants. This is down by use of the import static statement where you can import a single constant or all constants of a class.

import static com.example.MyConstants.PASS;
import static com.example.MyConstants.*;

To put it simply don’t define constants in an interface, instead create them properly in their own classes and if you really don’t want to qualify them then utilize static import to import the constants into your class.

References

, , , ,