How to insert into database when using JTA + JPA with Spring

1.6k views Asked by At

I have a simple web application using JTA + JPA along with Spring (version 4). I am doing a XA transaction using Atomikos JTA transaction Manager. This transaction involves inserting EmployeeA entity into DatabaseA and another EmployeeB entity into another DatabaseB.

Strangely, the application does not throw any error but no enteries are inserted into the Databases.

public class JtaTest {

public static void main( String[] args ) {

    JtaTest test = new JtaTest();
    test.testMandatory();
}

private static void testMandatory() {

    final SpringContextUtil util = SpringContextUtil.instance();
    ApplicationContext ctx = util.getApplicationContext();


    final JtaEmployeeService employeeService = (JtaEmployeeService)ctx.getBean("jtaEmployeeService");
    EmployeeA a = new EmployeeA();
    a.setName("emp-a-1");
    a.setAge(30);

    EmployeeB b = new EmployeeB();
    a.setName("emp-b-1");
    a.setAge(31);

   try {
    employeeService.persistEmployees(a, b);
    } catch (Exception e) {
    e.printStackTrace();
}   
   System.out.println("success");
}
}

The service class implementation:

@Service("jtaEmployeeService")
public class JtaEmployeeServiceImpl implements JtaEmployeeService {

@Autowired
@Qualifier("employeea")
private GenericDao<Integer, EmployeeA> employeeADao;


@Autowired
@Qualifier("employeeb")
private GenericDao<Integer, EmployeeB> employeeBDao;

@Override

@Transactional( propagation=Propagation.REQUIRED, readOnly=false, isolation=Isolation.DEFAULT, rollbackFor=Exception.class)
public void persistEmployees(EmployeeA employeeA, EmployeeB employeeB)  throws Exception {
    employeeADao.save(employeeA);
    employeeBDao.save(employeeB);
    System.out.println("Saving employee A and employee B ");


}
}

The DAO implementation and interfaces:


@Repository("employeeb")
public class EmployeeBDaoImpl extends AbstractJTADaoDatabaseB implements
    GenericDao<Integer, EmployeeB> {

@Override
public void save(EmployeeB entity) {
    super.persist(entity);

}
}

@Repository("employeea")
public class EmployeeADaoImpl extends AbstractJTADaoDatabaseA implements
    GenericDao<Integer, EmployeeA> {

@Override
public void save(EmployeeA entity) {
    super.persist(entity);

}
}

public abstract class AbstractJTADaoDatabaseB {

@PersistenceContext(unitName = "persistenceUnitB")
@Qualifier("myManager")
private EntityManager entityManager;

public void persist(Object entity) {
    entityManager.persist(entity);

    // entityManager.flush();
}

protected EntityManager getEntityManager() {
    return entityManager;
}

}

public abstract class AbstractJTADaoDatabaseA {

@PersistenceContext(unitName = "persistenceUnitA")
@Qualifier("myManager")
private EntityManager entityManager;

public void persist(Object entity) {
    entityManager.persist(entity);
    // entityManager.flush();
}

protected EntityManager getEntityManager() {
    return entityManager;
}

}

Servlet-Context.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:beans="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

 <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
 
 <!-- Enables the Spring MVC @Controller programming model -->
 <annotation-driven />
 
 <!--  Enables annotaion driven transactional support on springs -->
 <!-- <tx:annotation-driven transaction-manager="hTransactionManager"/> -->
 <!--  <tx:jta-transaction-manager transaction-manager="jtaTransactionManager"/> -->
 <tx:annotation-driven transaction-manager="jtaTransactionManager"/>

<!--  list the packages which are annotated with springs annotaions like @controller, @repository, @service, @component only -->
 <context:component-scan base-package="com.goraksh.spring.tutorial.controller.business, com.goraksh.spring.tutorial.controller.rest, com.goraksh.spring.tutorial.service, com.goraksh.spring.tutorial.dao" />

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <beans:property name="prefix" value="/WEB-INF/views/" />
      <beans:property name="suffix" value=".jsp" />
   </beans:bean>
   

 <beans:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <beans:property name="location" value="classpath:application.properties"/>
</beans:bean>

<!--  <beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean">  -->
<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <beans:property name="dataSource" ref="dataSource" />
    <beans:property name="hibernateProperties">
      <beans:props>
        <beans:prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</beans:prop>
       
       <!--  <beans:prop key="hibernate.current_session_context_class">thread</beans:prop> -->
         <beans:prop key="hibernate.show_sql">${hibernate.show_sql}</beans:prop>
          <beans:prop key="hibernate.format_sql">${hibernate.format_sql}</beans:prop>
           <beans:prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</beans:prop>
            <beans:prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</beans:prop>
             <beans:prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</beans:prop>
              <beans:prop key="net.sf.ehcache.configurationResourceName">${net.sf.ehcache.configurationResourceName}</beans:prop>
       
      </beans:props>
    </beans:property>
   
       <!--<beans:property name="annotatedClasses">  -->
  <!--  packagesToScan is meant to give the package where the javax.persistence.Entity classes are stored , recognised via their annotations-->
  <beans:property name="packagesToScan">
      <beans:list>
        <beans:value>com.goraksh.spring.tutorial.model</beans:value>
      </beans:list>
    </beans:property>
    
  </beans:bean>

<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <beans:property name="driverClassName" value="${jdbc.driverClassName}"/>
    <beans:property name="url" value="${jdbc.url}"/>
    <beans:property name="username" value="${jdbc.username}"/>
    <beans:property name="password" value="${jdbc.password}"/>
</beans:bean>

    
    <beans:bean id = "hTransactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
    <beans:property name = "sessionFactory" ref = "sessionFactory" />
</beans:bean>   
 
<!--  Jata transactions with Atomikos  -->
<beans:bean id="dataSourceA" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
 <beans:property name="uniqueResourceName"><beans:value>DataSourceA</beans:value></beans:property>
 <beans:property name="xaDataSourceClassName"><beans:value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</beans:value></beans:property>
 <beans:property name="xaProperties">
     <beans:props>
  <beans:prop key="databaseName">traningdb</beans:prop>
  <beans:prop key="serverName">localhost</beans:prop>
  <beans:prop key="port">3306</beans:prop>
  <beans:prop key="user">root</beans:prop>
  <beans:prop key="password">root</beans:prop>
  <beans:prop key="url">jdbc:mysql://localhost:3306/traningdb</beans:prop>
     </beans:props>
 </beans:property>
 <beans:property name="minPoolSize"><beans:value>1</beans:value></beans:property>
</beans:bean>
 
<beans:bean id="dataSourceB" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
 <beans:property name="uniqueResourceName"><beans:value>DataSourceB</beans:value></beans:property>
 <beans:property name="xaDataSourceClassName"><beans:value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</beans:value></beans:property>
 <beans:property name="xaProperties">
     <beans:props>
  <beans:prop key="databaseName">traningdb2</beans:prop>
  <beans:prop key="serverName">localhost</beans:prop>
  <beans:prop key="port">3306</beans:prop>
  <beans:prop key="user">root</beans:prop>
  <beans:prop key="password">root</beans:prop>
  <beans:prop key="url">jdbc:mysql://localhost:3306/traningdb2</beans:prop>
     </beans:props>
 </beans:property>
 <beans:property name="minPoolSize">
 <beans:value>1</beans:value>
 </beans:property>
</beans:bean>

<beans:bean id="entityManagerFactoryA" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <beans:property name="persistenceXmlLocation">
            <beans:value>classpath:META-INF/persistence.xml</beans:value>
    </beans:property>
  <beans:property name="persistenceUnitName" value="persistenceUnitA" />
  <beans:property name="dataSource" ref="dataSourceA" />
  <beans:property name="jpaVendorAdapter">
   <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <beans:property name="showSql" value="true" />
    <beans:property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
   </beans:bean>
  </beans:property>
 </beans:bean>
 
 <beans:bean id="entityManagerFactoryB" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <beans:property name="persistenceXmlLocation">
            <beans:value>classpath:META-INF/persistence.xml</beans:value>
        </beans:property>
  <beans:property name="persistenceUnitName" value="persistenceUnitB" />
  <beans:property name="dataSource" ref="dataSourceB" />
  <beans:property name="jpaVendorAdapter">
   <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <beans:property name="showSql" value="true" />
    <beans:property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
   </beans:bean>
  </beans:property>
 </beans:bean>

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

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

 <beans:bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"
  depends-on="atomikosTransactionManager,atomikosUserTransaction">
  <beans:qualifier value="myManager"/>
  <beans:property name="transactionManager" ref="atomikosTransactionManager" />
  <beans:property name="userTransaction" ref="atomikosUserTransaction" />
  <beans:property name="allowCustomIsolationLevels" value="true" />
 </beans:bean>

 
</beans:beans>


Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
  http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

 <persistence-unit name="persistenceUnitA" >
  <class>com.goraksh.spring.tutorial.model.EmployeeA</class>
  <exclude-unlisted-classes />
  <properties>


  <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />

  </properties>
 </persistence-unit>
  
 <persistence-unit name="persistenceUnitB" >
  <class>com.goraksh.spring.tutorial.model.EmployeeB</class>
  <exclude-unlisted-classes />
  <properties>

   <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />

  </properties>
 </persistence-unit>
  
</persistence>

Any help is highly solicited.

2

There are 2 answers

0
aknon On

After some additional tuning: 1. Removing all hibernate ( jpa properties ) from persistence.xml to the servlet-context.xml.

Added jpaProperties to EntityManagerFactoryA and EntityManagerFactoryB


Servlet-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:beans="http://www.springframework.org/schema/beans"
 xmlns:context="http://www.springframework.org/schema/context"
 xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
 xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd
  http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
  http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">

 <!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
 
 <!-- Enables the Spring MVC @Controller programming model -->
 <annotation-driven />
 
 <!--  Enables annotaion driven transactional support on springs -->
 <!-- <tx:annotation-driven transaction-manager="hTransactionManager"/> -->
 <!--  <tx:jta-transaction-manager transaction-manager="jtaTransactionManager"/> -->
 <tx:annotation-driven transaction-manager="jtaTransactionManager"/>

<!--  list the packages which are annotated with springs annotaions like @controller, @repository, @service, @component only -->
 <context:component-scan base-package="com.goraksh.spring.tutorial.controller.business, com.goraksh.spring.tutorial.controller.rest, com.goraksh.spring.tutorial.service, com.goraksh.spring.tutorial.dao" />

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
      <beans:property name="prefix" value="/WEB-INF/views/" />
      <beans:property name="suffix" value=".jsp" />
   </beans:bean>
   

 <beans:bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <beans:property name="location" value="classpath:application.properties"/>
</beans:bean>

<!--  <beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.annotation.AnnotationSessionFactoryBean">  -->
<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <beans:property name="dataSource" ref="dataSource" />
    <beans:property name="hibernateProperties">
      <beans:props>
        <beans:prop key="hibernate.dialect">org.hibernate.dialect.SQLServerDialect</beans:prop>
       
       <!--  <beans:prop key="hibernate.current_session_context_class">thread</beans:prop> -->
         <beans:prop key="hibernate.show_sql">${hibernate.show_sql}</beans:prop>
          <beans:prop key="hibernate.format_sql">${hibernate.format_sql}</beans:prop>
           <beans:prop key="hibernate.cache.region.factory_class">${hibernate.cache.region.factory_class}</beans:prop>
            <beans:prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</beans:prop>
             <beans:prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</beans:prop>
              <beans:prop key="net.sf.ehcache.configurationResourceName">${net.sf.ehcache.configurationResourceName}</beans:prop>
       
      </beans:props>
    </beans:property>
   
       <!--<beans:property name="annotatedClasses">  -->
  <!--  packagesToScan is meant to give the package where the javax.persistence.Entity classes are stored , recognised via their annotations-->
  <beans:property name="packagesToScan">
      <beans:list>
        <beans:value>com.goraksh.spring.tutorial.model</beans:value>
      </beans:list>
    </beans:property>
    
  </beans:bean>

<beans:bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <beans:property name="driverClassName" value="${jdbc.driverClassName}"/>
    <beans:property name="url" value="${jdbc.url}"/>
    <beans:property name="username" value="${jdbc.username}"/>
    <beans:property name="password" value="${jdbc.password}"/>
</beans:bean>

    
    <beans:bean id = "hTransactionManager" class = "org.springframework.orm.hibernate4.HibernateTransactionManager">
    <beans:property name = "sessionFactory" ref = "sessionFactory" />
</beans:bean>   
 
<!--  Jata transactions with Atomikos  -->
<beans:bean id="dataSourceA" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
 <beans:property name="uniqueResourceName"><beans:value>DataSourceA</beans:value></beans:property>
 <beans:property name="xaDataSourceClassName"><beans:value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</beans:value></beans:property>
 <beans:property name="xaProperties">
     <beans:props>
  <beans:prop key="databaseName">traningdb</beans:prop>
  <beans:prop key="serverName">localhost</beans:prop>
  <beans:prop key="port">3306</beans:prop>
  <beans:prop key="user">root</beans:prop>
  <beans:prop key="password">root</beans:prop>
  <beans:prop key="url">jdbc:mysql://localhost:3306/traningdb</beans:prop>
     </beans:props>
 </beans:property>
 <beans:property name="minPoolSize"><beans:value>1</beans:value></beans:property>
</beans:bean>
 
<beans:bean id="dataSourceB" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close">
 <beans:property name="uniqueResourceName"><beans:value>DataSourceB</beans:value></beans:property>
 <beans:property name="xaDataSourceClassName"><beans:value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</beans:value></beans:property>
 <beans:property name="xaProperties">
     <beans:props>
  <beans:prop key="databaseName">traningdb2</beans:prop>
  <beans:prop key="serverName">localhost</beans:prop>
  <beans:prop key="port">3306</beans:prop>
  <beans:prop key="user">root</beans:prop>
  <beans:prop key="password">root</beans:prop>
  <beans:prop key="url">jdbc:mysql://localhost:3306/traningdb2</beans:prop>
     </beans:props>
 </beans:property>
 <beans:property name="minPoolSize">
 <beans:value>1</beans:value>
 </beans:property>
</beans:bean>

<beans:bean id="entityManagerFactoryA" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <beans:property name="persistenceXmlLocation">
            <beans:value>classpath:META-INF/persistence.xml</beans:value>
    </beans:property>
  <beans:property name="persistenceUnitName" value="persistenceUnitA" />
  <beans:property name="dataSource" ref="dataSourceA" />
  <beans:property name="jpaVendorAdapter">
   <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <beans:property name="showSql" value="true" />
    <beans:property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />
  </beans:bean>
  </beans:property>
  
  <beans:property name="jpaProperties">  
           <beans:map>  
               <beans:entry key="hibernate.transaction.jta.platform" value-ref="atomikosJtaPlatform" />
                
               <beans:entry key="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />
            </beans:map>
          </beans:property>
          
 </beans:bean>
 
 <beans:bean id="entityManagerFactoryB" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
 <beans:property name="persistenceXmlLocation">
            <beans:value>classpath:META-INF/persistence.xml</beans:value>
        </beans:property>
  <beans:property name="persistenceUnitName" value="persistenceUnitB" />
  <beans:property name="dataSource" ref="dataSourceB" />
  <beans:property name="jpaVendorAdapter">
   <beans:bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
    <beans:property name="showSql" value="true" />
    <beans:property name="databasePlatform" value="org.hibernate.dialect.MySQL5InnoDBDialect" />    
   </beans:bean>
  </beans:property>
  
  <beans:property name="jpaProperties">  
           <beans:map>  
               <beans:entry key="hibernate.transaction.jta.platform" value-ref="atomikosJtaPlatform" />
               
               <beans:entry key="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />
            </beans:map>
          </beans:property>
               
 </beans:bean>
 
 <beans:bean id="atomikosJtaPlatform" class="com.goraksh.spring.atomikos.jta.platform.AtomikosJtaPlatform">
      <beans:constructor-arg index="0" ref="atomikosTransactionManager"/>
      <beans:constructor-arg index="1" ref="atomikosUserTransaction"/>
   </beans:bean>

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

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

 <beans:bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"
  depends-on="atomikosTransactionManager,atomikosUserTransaction">
  <beans:qualifier value="myManager"/>
  <beans:property name="transactionManager" ref="atomikosTransactionManager" />
  <beans:property name="userTransaction" ref="atomikosUserTransaction" />
  <beans:property name="allowCustomIsolationLevels" value="true" />
 </beans:bean>

 
</beans:beans>


Persistence.xml

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
  http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

 <persistence-unit name="persistenceUnitA" transaction-type="JTA" >
  <class>com.goraksh.spring.tutorial.model.EmployeeA</class>
  <exclude-unlisted-classes />
  <properties>

<!-- <property name="hibernate.transaction.jta.platform"       value="com.goraksh.spring.atomikos.jta.platform.AtomikosJtaPlatform" /> -->
  

  </properties>
 </persistence-unit>
  
 <persistence-unit name="persistenceUnitB" transaction-type="JTA">
  <class>com.goraksh.spring.tutorial.model.EmployeeB</class>
  <exclude-unlisted-classes />
  <properties>
<!-- <property name="hibernate.transaction.jta.platform"       value="com.goraksh.spring.atomikos.jta.platform.AtomikosJtaPlatform" /> -->
   

  </properties>
 </persistence-unit>
  
</persistence>

0
aknon On

After lot of head-whacking and many hit-and-trial debugging, finally able to solve the problem. Looks like below property is required in the persistence.xml

hibernate.transaction.jta.platform

On a application server there are multiple options available as Different JTA paltform services

But since I needed one standalone JTA platform implementation so I added one of my own.

com.goraksh.spring.atomikos.jta.platform.AtomikosJtaPlatform

So here is my modified persistence.xml:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0"
  xmlns="http://java.sun.com/xml/ns/persistence" 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://java.sun.com/xml/ns/persistence 
  http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">

 <persistence-unit name="persistenceUnitA" transaction-type="JTA" >
  <class>com.goraksh.spring.tutorial.model.EmployeeA</class>
  <exclude-unlisted-classes />
  <properties>

<property name="hibernate.transaction.jta.platform"       value="com.goraksh.spring.atomikos.jta.platform.AtomikosJtaPlatform" />
  <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />

  </properties>
 </persistence-unit>
  
 <persistence-unit name="persistenceUnitB" transaction-type="JTA">
  <class>com.goraksh.spring.tutorial.model.EmployeeB</class>
  <exclude-unlisted-classes />
  <properties>
<property name="hibernate.transaction.jta.platform"       value="com.goraksh.spring.atomikos.jta.platform.AtomikosJtaPlatform" />
   <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory" />

  </properties>
 </persistence-unit>
  
</persistence>

The source code for com.goraksh.spring.atomikos.jta.platform.AtomikosJtaPlatform

package com.goraksh.spring.atomikos.jta.platform;

import javax.transaction.TransactionManager;
import javax.transaction.UserTransaction;

import org.hibernate.engine.transaction.jta.platform.internal.AbstractJtaPlatform;

import com.atomikos.icatch.jta.UserTransactionImp;
import com.atomikos.icatch.jta.UserTransactionManager;

public final class AtomikosJtaPlatform extends AbstractJtaPlatform {

        private TransactionManager utm = new UserTransactionManager();
        
        private UserTransaction userTransaction = new UserTransactionImp();
        
        /**
         * 
         */
        private static final long serialVersionUID = -74991083213512919L;

        @Override
        protected TransactionManager locateTransactionManager() {
                return utm;
        }

        @Override
        protected UserTransaction locateUserTransaction() {
                return userTransaction;
        }

}