I recently tasked myself to put together a sample project using Atomikos TransactionsEssentials. This sample project consists of Spring 3, Hibernate 3.4, Apache ActiveMQ 5.3, and of course Atomikos TransactionsEssentials.
TransactionEssentials is an open source XA transaction manager built on top of their transaction kernel called ‘icatch‘. Essentials has basic support for JDBC/XA, JMS/XA, & JTA/XA. Once you register with Atomikos you will receive a link to download TransactionEsentials and a Maven repository url via email, we’ll proceed with the later.
Once you have the Atomikos maven repository url, either add it to the repository section of your pom.xml or add it to your internal maven repository.
<properties>
<atomikos.version>3.5.11</atomikos.version>
<activemq.version>5.3.1</activemq.version>
<springframework.version>3.0.2.RELEASE</springframework.version>
</properties>
<!--
Atomikos dependencies used for XA
-->
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-jms</artifactId>
<version>${atomikos.version}</version>
</dependency>
<dependency>
<groupId>com.atomikos</groupId>
<artifactId>transactions-hibernate3</artifactId>
<version>${atomikos.version}</version>
<exclusions>
<exclusion>
<artifactId>hibernate</artifactId>
<groupId>org.hibernate</groupId>
</exclusion>
</exclusions>
</dependency>
<!--
Microsoft JDBC driver
-->
<dependency>
<groupId>com.microsoft</groupId>
<artifactId>sqljdbc</artifactId>
<version>2.0.0</version>
</dependency>
<!--
Spring framework dependencies
-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${springframework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jms</artifactId>
<version>${springframework.version}</version>
</dependency>
<!--
Hibernate dependencies
-->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.4.0.GA</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.4.2</version>
</dependency>
<!--
ActiveMQ dependencies
-->
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-core</artifactId>
<version>${activemq.version}</version>
</dependency>
Here’s the spring configuration:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="userTransactionService" class="com.atomikos.icatch.config.UserTransactionServiceImp" init-method="init" destroy-method="shutdownForce">
<constructor-arg>
<props>
<prop key="com.atomikos.icatch.service">com.atomikos.icatch.standalone.UserTransactionServiceFactory</prop>
</props>
</constructor-arg>
</bean>
<bean id="AtomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close" depends-on="userTransactionService">
<!-- When close is called, should we force transactions to terminate or not? -->
<property name="forceShutdown" value="false" />
</bean>
<bean id="AtomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp" depends-on="userTransactionService">
<property name="transactionTimeout" value="300" />
</bean>
<!--
Configure the Spring framework to use JTA transactions from Atomikos
-->
<bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager" depends-on="userTransactionService">
<property name="transactionManager" ref="AtomikosTransactionManager" />
<property name="userTransaction" ref="AtomikosUserTransaction" />
</bean>
<bean id="datasource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
<property name="uniqueResourceName" value="XADBMS" />
<property name="xaDataSourceClassName" value="com.microsoft.sqlserver.jdbc.SQLServerXADataSource" />
<property name="xaProperties">
<!--
set the driver-specific XADataSource properties (check your driver docs for more info)
-->
<props>
<prop key="user">dbuser</prop>
<prop key="password">dbpass</prop>
<prop key="URL">jdbc:sqlserver://dev-server;databaseName=SomeDB;applicationName=XA-Sample</prop>
</props>
</property>
<property name="minPoolSize" value="1" />
<property name="maxPoolSize" value="50" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configLocation" value="classpath:hibernate.cfg.xml" />
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
<property name="dataSource" ref="datasource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.transaction.factory_class">com.atomikos.icatch.jta.hibernate3.AtomikosJTATransactionFactory</prop>
<prop key="hibernate.transaction.manager_lookup_class">com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup</prop>
</props>
</property>
</bean>
<bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<!-- ActiveMQ Setup -->
<bean id="jmsXaConnectionFactory" class="org.apache.activemq.ActiveMQXAConnectionFactory">
<property name="brokerURL" value="tcp://dev-server:61616" />
<property name="userName" value="user"/>
<property name="password" value="password"/>
</bean>
<!-- Configure the JMS connector; call init to register for recovery! -->
<bean id="amqConnectionFactory" class="com.atomikos.jms.AtomikosConnectionFactoryBean" init-method="init">
<property name="uniqueResourceName" value="XAactiveMQ" />
<property name="xaConnectionFactory" ref="jmsXaConnectionFactory" />
<property name="poolSize" value="5"/>
</bean>
<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
<property name="connectionFactory" ref="amqConnectionFactory"/>
<property name="receiveTimeout" value="2000" />
<property name="sessionTransacted" value="true" />
</bean>
<tx:annotation-driven transaction-manager="jtaTransactionManager" />
<context:component-scan base-package="com.company.application"/>
<context:annotation-config/>
And that’s about it for the setup of the infrastructure components. You should be able to @Autowire a JmsTemplate, PlatformTransactionManager (or use @Transactional) and SessionFactory in your application classes.
@Repository
public class SomeEntityDaoHibernateImpl implements SomeEntityDao {
@Autowired
private SessionFactory sessionFactory;
@Autowired
private JmsTemplate jmsTemplate;
@Transactional(readOnly=true)
public SomeEntity getSomeEntity(Integer entityId) {
return (SomeEntity ) sessionFactory.getCurrentSession().get(SomeEntity .class, entityId);
}
@Transactional(propagation=Propagation.REQUIRED)
public void updateSomeEntity (SomeEntity someEntity ) {
sessionFactory.getCurrentSession().update(someEntity );
jmsTemplate.convertAndSend("MyCompany.SomeCompany.UPDATE", "Entity updated ["+new Date()+"]: " + someEntity.toString() );
}

