'Atomikos / Spring - Global Transaction over two DBs

I am using Spring and trying to setup a global transaction spanning over two MS SQL Server DBs. The app is running inside Tomcat 6.

I have these definitions:

<bean id="dataSource1" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
....
</bean>

<bean id="sessionFactory1"
      class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource1"/>
....
</bean>

<bean id="hibernateTransactionManager1"
      class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref local="sessionFactory1"/>
    </property>
</bean>


<bean id="dataSource2" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
....
</bean>

<bean id="sessionFactory2"
      class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource2"/>
....
</bean>

<bean id="hibernateTransactionManager2"
      class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory">
        <ref local="sessionFactory2"/>
    </property>
</bean>

Then also, each DAO is linked either to sessionFactory1 or to sessionFactory2.

<bean name="stateHibernateDao" class="com.project.dao.StateHibernateDao">
      <property name="sessionFactory" ref="sessionFactory1"/>
</bean>

Also, I recently added these two.

<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method="close"> 
        <property name="forceShutdown" value="false" />
        <property name="transactionTimeout" value="300" />
</bean>

<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"> 
   <property name="transactionTimeout" value="300" /> 
</bean> 

I am trying to programmatically manage the global transaction (this is some old legacy code and I don't want to change it too much so I prefer keeping this managed programmatically).

So now I have this UserTransaction ut (injected from Spring), so I call ut.begin(), do some DB/DAO operations to the two DBs through the DAOs, then I call ut.commit().

The thing is that even before the ut.commit() call, I can see the data is already committed to the DBs?!

  1. I don't think Atomikos is aware of my two DBs, their data sources, session factories, etc. I don't think it starts any transactions on them. Looks like they are not enlisted at all in the global transaction.

  2. To me it seems that each DB/DAO operation goes to the SQL Server on its own, so SQL Server creates an implicit transaction for just that DAO/DB operation, applies the operation and commits the implicit the transaction.

But 1) and 2) are just guesses of mine.

My questions:

  1. Do I need to start the two DB transactions myself (but OK, this is what I am currently doing and I am trying to get rid of; that's why I am trying to use Atomikos to start with)?

  2. How I can configure all this correctly so that when I call ut.begin() it begins a global transaction to the two DBs and when I call ut.commit() it commits it?

  3. I haven't played with JTA recently so seems to me I am missing something quite basic here. What is it?

Edit 1

<bean id="globalTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="userTransaction" ref="atomikosUserTransaction"/>
    <property name="transactionManager" ref="atomikosTransactionManager" />
    <property name="allowCustomIsolationLevels" value="true" />
    <property name="transactionSynchronization" value="2" />
</bean>


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source