Tuesday, December 01, 2009

JTA Transactions with Atomkios in Tomcat

Tomcat is the leading Java Servlet container. Many of our applications do not need full blown Java EE Application Server and a Servlet container like Tomcat is more than enough to run them even in production. Some of our applications need JTA transactions capabilities, which are not provided by Tomcat out of the box. There are very few open source JTA implementations. JOTM used to be most popular among them, unfortunately its development is dead for last several years though it seems to getting revived lately at its new home. Atomikos is another JTA implementation, which was open sourced (Transactions Essentials) when JOTM went into hibernation.

Integrating Atomikos with Tomcat is fairly easy, it can be done by following simple steps given below-

Create a configuration file for Atomikos at $TOMCAT_HOME/lib/transactions.properties location with contents like below-

com.atomikos.icatch.service=com.atomikos.icatch.standalone.UserTransactionServiceFactory
com.atomikos.icatch.automatic_resource_registration=true
com.atomikos.icatch.output_dir=../work
com.atomikos.icatch.log_base_dir=../work
com.atomikos.icatch.enable_logging=true
com.atomikos.icatch.console_log_level=INFO

Define a DataSource in $TOMCAT_HOME/conf/context.xml as shown below-

<Transaction factory="com.atomikos.icatch.jta.UserTransactionFactory" />

<Resource name="jdbc/pgDS"
                auth="Container"
                type="com.atomikos.jdbc.AtomikosDataSourceBean"
                factory="com.vinodsingh.atomikos.tomcat.DataSourceBeanFactory"
                uniqueResourceName="jdbc/pgDS"
                xaDataSourceClassName="org.postgresql.xa.PGXADataSource"
                xaProperties.serverName="localhost"
                xaProperties.portNumber="5432"
                xaProperties.databaseName="test"
                xaProperties.user="test"
                xaProperties.password="test"
                maxPoolSize="3"
                minPoolSize="1" />

Copy following files to $TOMCAT_HOME/lib directory-
  • JDBC driver of the Database being used.
  • JTA API (jta-1.1.jar).
  • Atomikos Essentials (transactions-essentials-all-3.5.9.jar), name may change according to the version being used.
  • Tomcat integration jars available at Atomikos' site or atomikos-tomcat.jar built from the source code attached with this post.
All these changes will make UserTransaction object available in Tomcat's JNDI tree and it can be used in same way as we do in any regular Java EE application server. An example of using UserTransaction is shown in following code snippet-
public String insertRecord(String value) {
    UserTransaction utx = null;
    try {
        utx = ServiceLocator.getTrasactionManager();
        utx.begin();
        // Do transactional work
        pgDAO.insertRecord(value);

        // commit the transaction
        utx.commit();
    } catch (Exception e) {
        try {
            if (utx != null)
                utx.rollback();

            String msg = "Oops! Transaction is rolled back due to an exception";
            log.error(msg, e);
            return msg;
        } catch (Exception e1) {
            log.error("Failed to rollback the transaction", e1);
            return "Failed to rollback the transaction" + e1.getMessage();
        }
    }
    return "Transaction succeded";
}
To see transactions in action compile the attached source code, deploy the generated jta.war on Tomcat and open http://localhost:8080/jta/ URL in your browser. Thats all it takes to integrate Atomikos JTA transactions in Tomcat.

Note:-
  1. Though Atomikos' documentation about Tomcat 6 integration talks about configuring AtomikosLifecycleListener in $TOMCAT_HOME/conf/server.xml as well. But Atomikos seems to work well inside Tomcat without that configuration.
  2. Here I have slightly modified the code for Tomcat integration from what is available at Atomikos website, more details about the same will follow in upcoming posts.

Source code for this post is available here.

13 Comments:

Stefan Zobel said...

Very useful, thanks

Anonymous said...

Hi Vinod,

I have to implement distributed transactions with spring,tomcat and atomikos.
I could able to do it.
There is a small issue my datasources(two datasources for different databases) needs to be configured at tomcat level which i could not.

Please suggest me on how to implement the same.

Thanks & Regards

Anonymous said...

You should be able to configure one datasource for each database without any issues. Though if you want to share one datasource among various applications then this (Share a datasource among several applications in Tomcat using Atomikos) might be helpful to you.

Please elaborate just in case you are facing some other problem.

Anonymous said...

Hi Vinod,

I am using Spring 2.5, Tomcat6.x and i need to implement distributed transactions in one of my use case.

for this i want to declare 2 data sources at Tomcat level i.e in server.xml. as follows.





//The above configuration is taken from atomikos tomcat integration docs.

Now i need to access these datasources in my spring web application by declaring a bean which refers to the datasource in my applicationContext.xml.

I could not get how to do that.

Please guide me.



Thanks & Regards

Anonymous said...

Vinod

Datasource decl sample in tomcat

But how to configure in my spring applicationContext.xml to access this dataSource

Anonymous said...

The datasource needs to be configured in context.xml instead of server.xml. For lookup of datasource from Spring please have a look at this post JNDI lookup on Tomcat and JBoss using Spring

Anonymous said...

Vinod

I need to configure datasource(atomikos) in tomcat which can be accessible in my spring webapplication. My use case needs distributed transaction.

However if i configure com.atomikos.jdbc.AtomikosDataSourceBean in my spring applicationContext.xml it works fine. But i need to declare a distributed datasource at tomcat level and access it in my spring applicationContext.

Please guide me.

I could not paste the code here.

Please look @
My Blog

Thanks

Anonymous said...

Hi Vinod,

You think this is not a valid question?? or not looking @comments??

once again i repeat the question.

I need to configure an XA datasource(Atomikos library) at tomcat level and need to access the same in my spring web application as a jndi resource.

please guide me.

rama said...

Hi vinod,

i am using atomika with tomcat+springs,

in xa i am getting an error


com.atomikos.datasource.ResourceException: XA resource 'dataSource11':
resume for XID '636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D30303030313030303037:636F6D2E61746F6D696B6F732E737072696E672E6A6462632E746D31'
raised 0: unknown at com.atomikos.datasource.xa.XAResourceTransaction.resume(XAResourceTra

in my test server i am getting the issue 3 to 4 time a day.

i research on the issue in net some on told thatif we add

com.atomikos.icatch.serial_jta_transactions = false;

addove line in jta.properties this error wont repeat but i am getting the same error after writing that code in jta.props file.

please give me any solution.

urgent

ramakrishna

shijukuchelan said...

I have to implement distributed transactions with spring,tomcat5.5 , atomikos and mysql.
but when i trying to access my database i am getting the error
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'

my context.xml is

this and my web.xml is

esource-ref>
PaymentsDatabase
jdbc/welcome
javax.sql.DataSource
Container
Shareable


where i have done mistake

shijukuchelan said...

dear Vinod
I have to implement distributed transactions with spring,tomcat 5.5 , atomikos and mysql, but when i am trying to access the database i m getting the error like this.
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is org.apache.tomcat.dbcp.dbcp.SQLNestedException: Cannot create JDBC driver of class '' for connect URL 'null'

my tomcat/config/context.xml is

and my web.xml is

PaymentsDatabase
jdbc/welcome
javax.sql.DataSource
Container
Shareable


where i have done mistakes ..

IceMan said...

Hi Vinod,

So efficient and outstanding your post! Congratulations!!! ;-))

But, now I have a small doubt.
U stated that a "UserTransaction object available in Tomcat's JNDI.."
I just would like to know if is it posssible a configuration within I could re(bind) a
'com.atomikos.icatch.jta.UserTransactionManager' (instead of UserTransactionImp/com.atomikos.icatch.jta.UserTransactionFactory) within JNDI of TomCat (context)??!

Thanks in advance,

IceMan

gogaak said...

hi Vinod,

Great article,

Do we have any option for init sql to set the schema for a datasource. Somthing like "initConnectionSql".

Thanks
Shailesh