I would like to configure the two Data sources one is Oracle and one is My-SQL to the Transaction Manager in the Spring JTA to perform the 2 phase commit so that any one transaction of the any of the Data sources get failed and the spring JTA needs to perform the roll back on the both of the data sources
*Heard the atomikos can we used to configure this kind of scenarios Please provide the some configuration codes are anything that would be useful in implementing this code *
Git url for the entire code: https://github.com/mageshsrinivasulu/poc
spring-beans.xml:
<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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean class="org.springframework.beans.factory.config
.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:Application.properties" />
</bean>
<bean id="oracleSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="oracleDataSource" />
<property name="mappingResources">
<list>
<value>persons.hbm.xml </value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<prop key="hibernate.autocommit">false</prop>
<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.max_size">10</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
</props>
</property>
</bean>
<bean id="mysqlSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mysqlDataSource" />
<property name="mappingResources">
<list>
<value>persons.hbm.xml </value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.autocommit">false</prop>
<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.max_size">10</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
</props>
</property>
</bean>
<!-- Creating TransactionManager Bean, since JDBC we are creating of type
DataSourceTransactionManager -->
<bean id="oracleTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="oracleDataSource" />
</bean>
<bean id="mysqlTransactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="mysqlDataSource" />
</bean>
<bean id="oracleDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${oracle.hibernate.connection.driver_class}" />
<property name="url" value="${oracle.hibernate.connection.url}" />
<property name="username" value="${oracle.Username}" />
<property name="password" value="${oracle.Password}" />
</bean>
<bean id="mysqlDataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${mysql.jdbc.driverClassName}" />
<property name="url" value="${mysql.hibernate.connection.url}" />
<property name="username" value="${mysql.Username}" />
<property name="password" value="${mysql.Password}" />
</bean>
<bean id="persons" class="com.bnym.aal.poc.spring_jta.Persons">
</bean>
<bean id="App" class="com.bnym.aal.poc.spring_jta.App">
<property name="springJtaDaoClass" ref="springJtaDaoClass" />
</bean>
<bean id="springJtaDaoClass" class="com.bnym.aal.poc.spring_jta.springJtaDaoClass">
<property name="oracleSessionFactory" ref="oracleSessionFactory" />
<property name="mysqlSessionFactory" ref="mysqlSessionFactory" />
<property name="oracleTransactionManager" ref="oracleTransactionManager" />
<property name="mysqlTransactionManager" ref="mysqlTransactionManager" />
<property name="persons" ref="persons" />
</bean>
springJtaDaoClass
import java.io.Serializable;
import java.util.List;
import javax.sql.DataSource;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
package com.bnym.aal.poc.spring_jta;
public class springJtaDaoClass implements Serializable
{
/**
*
*/
private static final long serialVersionUID = 1L;
private static SessionFactory oracleSessionFactory;
private static SessionFactory mysqlSessionFactory;
private HibernateTemplate oracleJdbcTemplateObject;
private HibernateTemplate mysqlJdbcTemplateObject;
private static Persons persons;
public static SessionFactory getOracleSessionFactory() {
return oracleSessionFactory;
}
public void setOracleSessionFactory(SessionFactory oracleSessionFactory) {
springJtaDaoClass.oracleSessionFactory = oracleSessionFactory;
this.oracleJdbcTemplateObject=new HibernateTemplate(oracleSessionFactory);
}
public static SessionFactory getMysqlSessionFactory() {
return mysqlSessionFactory;
}
public void setMysqlSessionFactory(SessionFactory mysqlSessionFactory) {
springJtaDaoClass.mysqlSessionFactory = mysqlSessionFactory;
this.mysqlJdbcTemplateObject=new HibernateTemplate(mysqlSessionFactory);
}
public static PlatformTransactionManager oracleTransactionManager;
public static PlatformTransactionManager mysqlTransactionManager;
public static PlatformTransactionManager getOracleTransactionManager() {
return oracleTransactionManager;
}
public static void setOracleTransactionManager(PlatformTransactionManager
oracleTransactionManager) {
springJtaDaoClass.oracleTransactionManager = oracleTransactionManager;
}
public static PlatformTransactionManager getMysqlTransactionManager() {
return mysqlTransactionManager;
}
public static void setMysqlTransactionManager(PlatformTransactionManager
mysqlTransactionManager) {
springJtaDaoClass.mysqlTransactionManager = mysqlTransactionManager;
}
public static Persons getPersons() {
return persons;
}
public static void setPersons(Persons persons) {
springJtaDaoClass.persons = persons;
}
public void dbOracleAccess()
{
TransactionDefinition oracledef= new DefaultTransactionDefinition();
TransactionStatus oraclestatus =
oracleTransactionManager.getTransaction(oracledef);
try
{
Persons person1=getPersons().persons(1,"a","b","c","d");
oracleJdbcTemplateObject.save(person1);
oracleTransactionManager.commit(oraclestatus);
}
catch (DataAccessException e) {
System.out.println("Error in creating record, rolling back");
oracleTransactionManager.rollback(oraclestatus);
throw e;
}
}
public void dbMySqlAccess()
{
TransactionDefinition mysqldef= new DefaultTransactionDefinition();
TransactionStatus
mysqlstatus=mysqlTransactionManager.getTransaction(mysqldef);
try
{
Persons person2=getPersons().persons(2,"e","b","c","d");
mysqlJdbcTemplateObject.save(person2);
mysqlTransactionManager.commit(mysqlstatus);
}
catch (DataAccessException e) {
System.out.println("Error in creating record, rolling back");
mysqlTransactionManager.rollback(mysqlstatus);
throw e;
}
}
}
Below is the working code of the above stated issue:
Entire project for the Atomikos Transaction manager for the connecting the two data sources to the single transaction manager by out of box integration would be available in the below GIT url
https://github.com/mageshsrinivasulu/spring-jta.git
spring-beans.xml
<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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:Application.properties" />
</bean>
<bean id="oracleSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="oraclesDataSource" />
<property name="mappingResources">
<list>
<value>persons.hbm.xml </value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
<!-- <prop key="hibernate.autocommit">true</prop> <prop key="hibernate.connection.isolation">3</prop> -->
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">
org.hibernate.transaction.CMTTransactionFactory
</prop>
<prop key="hibernate.transaction.manager_lookup_class">
com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
</prop>
<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.max_size">10</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
</props>
</property>
</bean>
<bean id="mysqlSessionFactory"
class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
<property name="dataSource" ref="mysqlDataSource" />
<property name="mappingResources">
<list>
<value>persons.hbm.xml </value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<!-- <prop key="hibernate.autocommit">ture</prop> <prop key="hibernate.connection.isolation">3</prop> -->
<prop key="hibernate.current_session_context_class">jta</prop>
<prop key="hibernate.transaction.factory_class">
org.hibernate.transaction.CMTTransactionFactory
</prop>
<prop key="hibernate.transaction.manager_lookup_class">
com.atomikos.icatch.jta.hibernate3.TransactionManagerLookup
</prop>
<!-- <prop key="hibernate.current_session_context_class">thread</prop> -->
<prop key="hibernate.c3p0.min_size">5</prop>
<prop key="hibernate.c3p0.max_size">10</prop>
<prop key="hibernate.c3p0.timeout">300</prop>
</props>
</property>
</bean>
<tx:annotation-driven proxy-target-class="true" />
<tx:jta-transaction-manager
transaction-manager="atomikosTransactionManager" />
<tx:annotation-driven transaction-manager="atomikosTransactionManager"
proxy-target-class="true" />
<bean id="atomikosTransactionManager" class="com.atomikos.icatch.jta.UserTransactionManager"
init-method="init" destroy-method="close">
<property name="forceShutdown" value="false" />
</bean>
<bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.J2eeUserTransaction">
<property name="transactionTimeout" value="300" />
</bean>
<tx:annotation-driven />
<bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"
depends-on="atomikosTransactionManager,atomikosUserTransaction">
<property name="transactionManager" ref="atomikosTransactionManager" />
<property name="userTransaction" ref="atomikosUserTransaction" />
<property name="allowCustomIsolationLevels" value="true" />
</bean>
<bean id="mysqlDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>mySqlDataSource</value>
</property>
<property name="xaDataSourceClassName">
<value>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</value>
</property>
<property name="xaProperties">
<props>
<prop key="databaseName">sys</prop>
<prop key="serverName">localhost</prop>
<prop key="port">3306</prop>
<prop key="user">root</prop>
<prop key="password">magesh123</prop>
<prop key="url">jdbc:mysql://localhost:3306/sys</prop>
</props>
</property>
<property name="minPoolSize">
<value>1</value>
</property>
</bean>
<bean id="oraclesDataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean"
init-method="init" destroy-method="close">
<property name="uniqueResourceName">
<value>OracleDataSource</value>
</property>
<property name="xaDataSourceClassName">
<value>oracle.jdbc.xa.client.OracleXADataSource</value>
</property>
<property name="xaProperties">
<props>
<prop key="databaseName">XE</prop>
<prop key="serverName">localhost</prop>
<!-- <prop key="port">1521</prop> -->
<prop key="user">system</prop>
<prop key="password">magesh123</prop>
<prop key="URL">jdbc:oracle:thin:@localhost:1521:XE</prop>
</props>
</property>
<property name="minPoolSize">
<value>1</value>
</property>
</bean>
<bean id="persons" class="com.bnym.aal.poc.spring_jta.Persons">
</bean>
<bean id="App" class="com.bnym.aal.poc.spring_jta.App">
<property name="springJtaDaoClass" ref="springJtaDaoClass" />
</bean>
<bean id="springJtaDaoClass" class="com.bnym.aal.poc.spring_jta.springJtaDaoClass">
<property name="oracleSessionFactory" ref="oracleSessionFactory" />
<property name="mysqlSessionFactory" ref="mysqlSessionFactory" />
<property name="atomikosTransactionManager" ref="transactionManager" />
<property name="persons" ref="persons" />
</bean>
springJtaDaoClass.java
package com.bnym.aal.poc.spring_jta;
import java.io.Serializable;
import org.hibernate.FlushMode;
import org.hibernate.Hibernate;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate4.HibernateTemplate;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
public class springJtaDaoClass implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private static SessionFactory oracleSessionFactory;
private static SessionFactory mysqlSessionFactory;
private HibernateTemplate oracleJdbcTemplateObject;
private HibernateTemplate mysqlJdbcTemplateObject;
private static Persons persons;
public static SessionFactory getOracleSessionFactory() {
return oracleSessionFactory;
}
public void setOracleSessionFactory(SessionFactory oracleSessionFactory) {
springJtaDaoClass.oracleSessionFactory = oracleSessionFactory;
this.oracleJdbcTemplateObject = new
HibernateTemplate(oracleSessionFactory);
}
public static SessionFactory getMysqlSessionFactory() {
return mysqlSessionFactory;
}
public void setMysqlSessionFactory(SessionFactory mysqlSessionFactory) {
springJtaDaoClass.mysqlSessionFactory = mysqlSessionFactory;
this.mysqlJdbcTemplateObject = new
HibernateTemplate(mysqlSessionFactory);
}
public static PlatformTransactionManager atomikosTransactionManager;
public static PlatformTransactionManager getAtomikosTransactionManager() {
return atomikosTransactionManager;
}
public static void setAtomikosTransactionManager(PlatformTransactionManager
atomikosTransactionManager) {
springJtaDaoClass.atomikosTransactionManager =
atomikosTransactionManager;
}
public static Persons getPersons() {
return persons;
}
public static void setPersons(Persons persons) {
springJtaDaoClass.persons = persons;
}
@Transactional()
public void daoWrapper() throws Exception {
atomikosTransactionManager = getAtomikosTransactionManager();
TransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status =
atomikosTransactionManager.getTransaction(def);
Persons person1 = new Persons();
person1.persons(2, "a", "b", "c", "d");
try {
getMysqlSessionFactory().getCurrentSession().save(person1);
getOracleSessionFactory().getCurrentSession().save(person1);
atomikosTransactionManager.commit(status);
} catch (Exception e) {
System.out.println("Error in creating record, rolling back");
atomikosTransactionManager.rollback(status);
e.printStackTrace();
}
}
}