Integrating BTM with iBatis
iBatis can be integrated straight with any JTA transaction manager. These instructions have been verified against BTM 1.2.
|Table of Contents|
iBatis cannot directly create a BTM
PoolingDataSource. You will have to create them yourself (either via the API or the Resource Loader) and make sure they are bound to a JNDI server.
Setting up a JNDI server
You have to bind the datasources to some JNDI server. You can use any one you wish, including the one embedded in your application server.
This will configure Tomcat's JNDI server as the default implementation. It is a simple intra-VM server that implements the most important JNDI features. You can now just create a InitialContext with the no-args constructor to have access to it.
API way: Creating the datasources
As you can expect, you will need to create one
PoolingDataSource per database. Say that you want to use two Embedded Derby databases, and configure them via the BTM API. Here is what your code would look like:
Context ctx = new InitialContext(); ctx.createSubcontext("jdbc"); ctx.rebind("jdbc/testDS1", ds1); ctx.rebind("jdbc/testDS2", ds2); ctx.close();
Resource Loader way: Creating the datasources
You can use BTM's Resource Loader instead of the BTM API. It is usually a good idea when you want to create a fully standalone application as you can get rid of the datasources creation, JNDI binding and shutdown code.
This has the exact same behavior as creating the
PoolingDataSource objects and binding them to JNDI yourself. It is just more convenient.
You need to configure exactly one
SqlMapClient per datasource.
Datasource JNDI location
You have to tell iBatis where to get the BTM datasource via JNDI. Add a
DataSource property to the
dataSource tag and set its value to the JNDI location of your datasource:
<dataSource type="JNDI"> <property name="DataSource" value="jdbc/testDS1"/> </dataSource>
Transaction Manager JNDI location
You have to set
transactionManager tag's type attribute to
JTA and wrap the
dataSource tag in it.
<transactionManager type="JTA" > <property name="UserTransaction" value="UserTransaction"/> <dataSource type="JNDI"> <property name="DataSource" value="jdbc/testDS1"/> </dataSource> </transactionManager>
SqlMapConfig XML configuration files
Here is what the
SqlMapConfig1.xml file will look like for the first datasource.
<?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> <transactionManager type="JTA" > <property name="UserTransaction" value="UserTransaction"/> <dataSource type="JNDI"> <property name="DataSource" value="jdbc/testDS2"/> </dataSource> </transactionManager> <sqlMap resource="bitronix/examples/ibatis/entities/User.xml"/> </sqlMapConfig>
Now that iBatis and BTM are properly configured, you can simply use the JTA and iBatis APIs in your application.
Here is what your code will look like when you want to update the content of both databases atomically:
persistUser() creates a new user, in no way will a user be created in one database and not in the other.
You can download a sample runnable application putting these explanations in practice. It contains all the code that has been skipped for clarity in this page. Both the API and Resource Loader ways are implemented so you can try both and see which one you prefer.