Wednesday, December 14, 2005

How to use the Middlegen generated iBATIS/DAO/Spring code

If you were following my previous entry, iBATIS, DAO, Spring and Middlegen code generation, you will recall I had used the development version of the Middlegen iBATIS plugin (available from the Middlegen CVS or you can download a version of it here) to generate the iBATIS XML SqlMapping file and the transparent domain objects. I had also extended this plugin by adding additional Velocity template files to additionally produce simple versions of the DAO interface, DAO implementation (using Spring's SqlMapClientTemplate), Facade interface and Facade implementation. So now you have all the config and classes you need to actually get something working. To provide some closure for the previous blog entry this entry will describe the final steps you need to do in order to use the generated code.

You will need a sqlmap-config.xml file, this could probably also be generated. In this simple example with only one table in the database it will only refer to a single SQLMapping file but essentially this file serves to collate the various SQLMapping files together.


<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE sqlMapConfig PUBLIC
"-//iBATIS.com//DTD SQL Map Config 2.0//EN"
"http://www.ibatis.com/dtd/sql-map-config-2.dtd"
>

<sqlMapConfig>
<sqlMap resource="Item.xml"/>
</sqlMapConfig>

With the ApplicationContext.xml we finally see where Spring does its magic. Here we define all the beans we need and actually perform the "injections" to which the phrase dependency injection actually refers. So we define our datasource, SqlMapClientFactoryBean and inject these into our iBATIS/Spring enabled ItemDao implementation (SqlMapItemDao). In turn our SqlMapItemDao is then injected into our Facade implementation.


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">

<beans>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName">
<value>org.apache.derby.jdbc.EmbeddedDriver</value>
</property>
<property name="url">
<value>jdbc:derby:build/derby/simpledb</value>
</property>
</bean>

<bean id="sqlMapClient" class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<property name="configLocation"><value>sqlmap-config.xml</value></property>
</bean>

<bean id="itemDAO" class="mypackage.sqlmapdao.SqlMapItemDao">
<property name="dataSource"><ref local="dataSource"/></property>
<property name="sqlMapClient"><ref local="sqlMapClient"/></property>
</bean>

<bean id="facade" class="mypackage.domain.logic.FacadeImpl">
<property name="itemDao"><ref local="itemDAO"/></property>
</bean>

</beans>

My first steps with Spring were following David Caruana's Spring Start - "Where do I Start?" For Developers. This is a getting started guide and tutorial with a collection of concise codeexamples that step you through the basic Spring Framework capabilities.

Modifiying one of David's examples to work with my generated code I get the following Main.java. Essentially this class initialises Spring to use the ApplicationContext.xml configuration file. I can then use the Spring factory to obtain instances of the defined beans. This class shows how I can create an instance of my domain object and then pass it to and from the datasource using the facade I have established. Notice how there is no need to import the implementation packages as the actual implementation classes have already been defined in the ApplicationContext.xml file. Granted I still have to do a little exception handling to help maintain referential integrity (so that I don't try and add mutliple Items with the same primary key etc.) but all in all this is very simple and it feels like I am at last doing DAO right!


import mypackage.domain.Item;
import mypackage.domain.logic.Facade;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;

public class Main {

public static void main(String[] args)
throws Exception {
// Manually create the Spring Bean Factory
// Note: The factory is driven by the Bean definitions held in ApplicationContext
// Note: There are also other implementations of Resource and Factory, but
// the following combination work well for standalone apps.

ClassPathResource res = new ClassPathResource("ApplicationContext.xml");
XmlBeanFactory factory = new XmlBeanFactory(res);

{
Facade facade = (Facade) factory.getBean("facade");
Item item = new Item();
item.setItemId("item1");
facade.insertItem(item);
Item item2 = facade.getItem("item1");
System.out.println(item2.getItemId());
facade.deleteItem(item);
}

System.out.println("Done");
}

}

Following my iBATIS/Middlegen blog entry, Olivier Ziller brought my attention to an alternative way of generating iBATIS and DAO code using iBATIS Abator. After a preliminary look at Abator I have come to the conclusion that I would still prefer to use Middlegen. I found that it was quite easy to modify the generated code that Middlegen produces by simply editing Velocity template files. However, it is great to know that there are alternative tools out there covering the same ground as it adds further weight to my growing belief that this is the right way to go.

0 comments: