SimpleJTA V2 User's Guide

Overview

SimpleJTA provides an implementation of the UserTransaction interface. It also provides pooled Datasource implementations. At present, Oracle and Derby datasource implementations are provided. It is easy to add support for other datasources.

An application wishing to use SimpleJTA V2 needs to perform following simple steps:

Create the transaction log tables

SimpleJTA requires a database to store its transaction log. The transaction log tables can reside in one of the databases that will be involved in JTA transactions, or they can reside in an embedded or network Derby database.

The vendor specific script create_tables.sql can be found in the subdirectory src/main/sql/tm in the distribution. Run the appropriate script against the database of your choice. At present, Oracle and Derby implementations are provided.

In following sections we will refer to the database that holds transaction log tables as the TLOG database.

Configure SimpleJTA V2

SimpleJTA V2 uses SpringFramework to manage objects internally.

Each instance of SimpleJTA requires its own Spring ApplicationContext. SimpleJTA uses Spring's SingletonBeanFactoryLocator to locate its ApplicationContext. Instead of the default "classpath*:beanRefFactory.xml" it uses "classpath*:SimpleJTA.xml". A Spring configuration file named SimpleJTA.xml must therefore be present in the classpath. Following shows the contents of such a file:

<?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="myapp"
        class="org.springframework.context.support.ClassPathXmlApplicationContext">
    <constructor-arg>
      <value>applicationContext.xml</value>
    </constructor-arg>
  </bean>
</beans>

Notice that above file contains a single bean definition. This is an instance of Spring ApplicationContext, as defined in the configuration file named applicationContext.xml. The advantage of using the BeanFactoryLocator pattern is that it allows clients to define the location of the configuration file. In the example shown above, we have defined this to be on the classpath, but you can choose to have it elsewhere.

Contents of SimpleJTA's main configuration file

SimpleJTA's main configuration file contains definitions of the following beans.

Transaction Log

Each instance of SimpleJTA requires access to a set of database tables that are used to store transaction data. You define the Transaction Log in two steps:

First, you define an instance of org.simplejta.tm.log.jdbc.JDBCTransactionLogAdaptor. In the following example we use a Derby adaptor that comes with SimpleJTA. You can choose to implement your own version to support a database of your choice.

<bean id="tlogAdaptor" class="org.simplejta.tm.log.jdbc.adaptors.DerbyEmbeddedTransactionLogAdaptor" >
 <property name="url" value="/derby/databases/tca" />
 <property name="user" value="APP" />
 <property name="password" value="APP" />
</bean>

The next step is to define an instance of org.simplejta.tm.log.jdbc.JDBCTransactionLog, and inject the JDBCTransactionLogAdaptor implementation.

<bean id="tlog"
  class="org.simplejta.tm.log.jdbc.JDBCTransactionLog">
  <property name="jdbcTransactionLogAdaptor" ref="tlogAdaptor" />
</bean>

Although the default implementation of a Transaction Log uses a database, if you wish you can use some other storage mechanism, such as files, by providing your own custom implementation of the org.simplejta.tm.log.TransactionLog interface.

Transaction Manager

Next you define an instance of SimpleJTA's Transaction Manager implementation:

<bean id="myTM" class="org.simplejta.tm.SimpleTransactionManager">
  <property name="transactionLog" ref="tlog" />
</bean>

The bean ID (in bold) of the Transaction Manager acts as a key for clients, and also as an internal key for Xids and entries in the Transaction Log. Hence it is important to ensure that this ID is unique within the context of the application.

JDBC and JMS Adaptors

SimpleJTA V2 uses JDBC and JMS Adaptors to encapsulate vendor specific behaviour. JDBC Adaptors must implement the org.simplejta.tm.jdbc.JDBCDataSourceAdaptor interface, and JMS Adaptors must implement the org.simpljta.tm.jms.JMSConnectionFactoryAdaptor interface. SimpleJTA V2 comes with pre-built adaptors for Oracle, Apache Derby and ActiveMQ. Following snippet from the configuration file shows how these adaptors are registered:

<bean id="DERBY.EMBEDDED.ADAPTOR" class="org.simplejta.tm.jdbc.adaptors.DerbyEmbeddedDataSourceAdaptor" />
<bean id="ORACLE.ADAPTOR" class="org.simplejta.tm.jdbc.adaptors.OracleDataSourceAdaptor" />
<bean id="ACTIVEMQ.ADAPTOR" class="org.simplejta.tm.jms.adaptors.ActiveMQJMSConnectionFactoryAdaptor" />

Connection Pools

The final step is to define the JDBC or JMS Connection Pools. An example of a JDBC Connection Pool is shown below:

<bean id="DerbyConnectionPool"
 class="org.simplejta.tm.jdbc.JDBCXAConnectionPool">
  <property name="dataSourceAdaptor" ref="DERBY.EMBEDDED.ADAPTOR" />
  <property name="transactionManager" ref="myTM" />
  <property name="connectionProperties">
    <props>
      <prop key="databaseName">/derby/databases/tca</prop>
      <prop key="user">APP</prop>
      <prop key="password">APP</prop>
    </props>
  </property>
</bean>

In the example above, we have used the Derby Embedded adaptor.

Note that each instance of a Connection Pool can have its own set of connection properties. The interpretation of the connection properties is upto the JDBC DataSource Adaptor implementation; see the documentation for supplied adaptors for more details of the supported properties.

Given below is an example of JMS Connection Pool:

<bean id="ActiveMQConnectionPool" class="org.simplejta.tm.jms.JMSXAConnectionPool">
  <property name="connectionFactoryAdaptor" ref="ACTIVEMQ.ADAPTOR" />
  <property name="transactionManager" ref="myTM" />
  <property name="connectionProperties">
    <props>
      <prop key="brokerURL">tcp://localhost:61616</prop>
      <prop key="userName"></prop>
      <prop key="password"></prop>
    </props>
  </property>
</bean>

Client configuration

SimpleJTA's client API consists of small number of classses:

org.simplejta.tm.ut.SimpleUserTransaction
This is an implementation of javax.transaction.UserTransaction .
org.simplejta.tm.jdbc.SimpleJTADataSource
This is an implementation of javax.sql.DataSource .
org.simplejta.tm.jms.SimpleJTAJMSConnectionFactory
Provides an implementation of javax.jms.ConnectionFactory .

Given below are three different ways of creating instances of above classes.

Using new operator

The constructor for SimpleUserTransaction takes a single argument, a Properties object. The following properties are mandatory:

beanFactory
must contain the name of the bean that contains SimpleJTA's ApplicationContext. In the example shown before, this is "myapp".
transactionManager
must contain the name of the bean that defines an instance of SimpleJTA's Transaction Manager. In the example shown above, this is "myTM".

Example:

Properties props = new Properties();
props.setProperty("beanFactory", "myapp");
props.setProperty("transactionManager", "myTM");
UserTransaction ut = new SimpleUserTransaction(props);

Creating data sources is equally simple. The SimpleJTADataSource requires three properties to be set:

beanFactory
must contain the name of the bean that contains SimpleJTA's ApplicationContext. In the example shown before, this is "myapp".
transactionManager
must contain the name of the bean that defines an instance of SimpleJTA's Transaction Manager. In the example shown above, this is "myTM".
connectionPool
Name of the bean that defines the connection pool.

Example:

SimpleJTADataSource ds = new SimpleJTADataSource();
ds.setBeanFactory("myapp");
ds.setTransactionManager("myTM");
ds.setConnectionPool("DerbyConnectionPool");

Notice that both SimpleUserTransaction and SimpleJTADataSource require the beanFactory and transactionManager properties. SimpleJTADataSource also contains a reference to the JDBC Connection Pool implementation.

Creating JMS Connection Factories is equally easy. Here is an example:

SimpleJTAJMSConnectionFactory qcf = new SimpleJTAJMSConnectionFactory();
qcf.setBeanFactory("myapp");
qcf.setTransactionManager("myTM");
qcf.setConnectionPool("ActiveMQConnectionPool");

Using SpringFramework Bean factory

It is fairly simple to configure the SimpleUserTransaction and SimpleJTADataSource using SpringFramework bean definitions.

<?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="UserTransaction" class="org.simplejta.tm.ut.SimpleUserTransaction">
    <constructor-arg>
      <props>
        <prop key="beanFactory">myapp</prop>
        <prop key="transactionManager">myTM</prop>
      </props>
    </constructor-arg>
  </bean>
  <bean id="DataSource1" class="org.simplejta.tm.jdbc.SimpleJTADataSource">
    <property name="beanFactory" value="myapp" />
    <property name="transactionManager" value="myTM" />
    <property name="connectionPool" value="DerbyConnectionPool" />
  </bean>
  <bean id="ActiveMQ.QCF" class="org.simplejta.tm.jms.SimpleJTAJMSConnectionFactory">
    <property name="beanFactory" value="myapp" />
    <property name="transactionManager" value="myTM" />
    <property name="connectionPool" value="JMSConnectionPool1" />
  </bean>
</beans>

Integrating with Tomcat JNDI Context

Following shows how to integrate SimpleJTA with Tomcat's JNDI implementation. Note that this description applies to Tomcat 5.5.9 and above.

Libraries

Copy SimpleJTA and other required libraries in the server's common/lib folder. Placing libraries in WEB-INF/lib does not work as Tomcat needs to be able to access the SimpleJTA classes when registering resources in JNDI. You will require the jar files for SimpleJTA, SpringFramework, Log4J, JMS and JTA. You will also need vendor specific jar files for appropriate JDBC or JMS clients.

Declare resource requirements

In your web applications web.xml file, declare the resources your application will use. You must declare the UserTransaction resource and one or more Datasource resources. And example is given below:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
    ...
    <resource-env-ref>
        <resource-env-ref-name>jta/UserTransaction</resource-env-ref-name>
        <resource-env-ref-type>javax.transaction.UserTransaction</resource-env-ref-type>
    </resource-env-ref>
    <resource-env-ref>
        <resource-env-ref-name>jdbc/Datasource</resource-env-ref-name>
        <resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
    </resource-env-ref>
    </web-app>

Configure Tomcat's Resource Factory

Create context.xml file in your application's META-INF folder, and configure your resources as shown in the example below:

<?xml version="1.0" encoding="UTF-8"?>
<Context path="/SimpleJTASample">
    <Resource name="jta/UserTransaction" auth="Container"
            type="javax.transaction.UserTransaction"
            factory="org.simplejta.tm.ut.SimpleUserTransactionFactory"
            beanFactory="myapp" transactionManager="myTM"
            />
    <Resource name="jdbc/Datasource" auth="Container"
            type="javax.sql.DataSource"
            factory="org.simplejta.tm.datasource.SimpleJTADataSourceFactory"
            className="org.simplejta.tm.datasource.SimpleJTADataSource"
            beanFactory="myapp" transactionManager="myTM"
            connectionPool="DerbyConnectionPool"
            />
</Context>      

Note the SimpleJTA provides custom implementations of ObjectFactory that can be used as Tomcat Resource Factories.

UserTransaction ObjectFactory
Tomcat Resource attribute Description
type javax.transaction.UserTransaction
factory org.simplejta.tm.ut.SimpleUserTransactionFactory
beanFactory The ID of SimpleJTA SpringFramework ApplicationContext bean in SimpleJTA.xml
transactionManager The ID of the SimpleJTA Transaction Manager bean.

Following table describes the attributes for Datasource Resource factories:

Datasource ObjectFactory
Tomcat Resource attribute Description
type javax.sql.DataSource
factory org.simplejta.tm.datasource.SimpleJTADataSourceFactory
className org.simplejta.tm.datasource.SimpleJTADataSource
beanFactory The ID of SimpleJTA SpringFramework ApplicationContext bean in SimpleJTA.xml
transactionManager The ID of the SimpleJTA Transaction Manager bean.
connectionPool ID of the ConnectionPool instance.


Write your code

Once you have created the SimpleUserTransaction object and the Datasources, you are ready to write code, much in the same way as you would with any UserTransaction implementation.

Example code in a Tomcat web application is shown below:

Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
UserTransaction ut = (UserTransaction) envCtx.lookup("jta/UserTransaction");
DataSource ds = (DataSource) envCtx.lookup("jdbc/Datasource");
          
ut.begin();
boolean success = false;
try {
  Connection conn = ds.getConnection();
  try {
    // do some work here
	success = true; // set if we completed our work
  }
  finally {
    if (conn != null) {
      conn.close();
    }
  }
}
finally {
  if (success)
    ut.commit();
  else
    ut.rollback();
}

General Usage Notes

Restart Recovery issues

See the Vendor Specific information page for more information regarding recovery issues.


SourceForge.net Logo