0 Replies Latest reply on May 31, 2012 9:58 AM by mauro.brasil

    Successful transaction with two datasources and no XA...

    mauro.brasil

      Hello there!

       

      I was implementing a data migration functionality on a application for the last week and I've find out a configuration that I supposed should not work at all, so I would like to check it out with you guys.

       

      The data migration involves two datasources. One points to a MySQL server (the source system) and the other to a PostgreSQL (destination system).

      I have already got the configuration so it gets working perfectly with two XA compliant datasources.

       

      The question is about a configuration that I've done during the lots of tests to get to final result that unexpectedly (at least for me) worked.

       

      Here are the spring persistency definitions:

       


      <bean id="dataSourceJboss" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">

      <property name="jndiName" value="${databaseJndi}" />

      </bean>



      <bean id="dataSourceMigration" class="org.springframework.jndi.JndiObjectFactoryBean" lazy-init="true">

      <property name="jndiName" value="${migrationDatabaseJndi}" />

      </bean>



      <bean id="sessionFactoryMigration" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

      <property name="dataSource" ref="dataSourceMigration" />



      <property name="useTransactionAwareDataSource" value="true" />



      <property name="hibernateProperties">

      <props>

      <prop key="hibernate.dialect">${migrationHibernateDialect}</prop>

      </props>

      </property>

       


      </bean>



      <bean id="abstractSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"

      abstract="true">

       


      <property name="useTransactionAwareDataSource" value="true" />



      <property name="hibernateProperties">

      <props>

      <prop key="hibernate.dialect">%[hibernateDialect]</prop>

      </props>

      </property>

       


      <property name="annotatedClasses">

      <list>

      </list>

      </property>

       


      </bean>



      <bean id="dataMigrationDAO" class="com.COMPANY.PRODUCT.migration.model.dao.impl.DataMigrationDAOImpl">

      <property name="sessionFactory" ref="sessionFactoryMigration" />

      </bean>

       

      For the sake of simplicity, I've omitted almost all "hibernateProperties" and all "annotatedClasses" tags contents.

       

      I've presented just the "dataMigrationDAO" that is the only one that uses "sessionFactoryMigration". The other were already present on the application before I've started this work and uses the "abstractSessionFactory".

       

      The data migration service is quite simple.

      It required just some application DAO's used mainly to collect information throghout the source system and "dataMigrationDAO" to registrate them on the destination system.

       

      A simplified description of service can be found below:

       


      <bean id="dataMigrationService" parent="baseTransactionProxy">

      <property name="target">

      <bean class="com.COMPANY.PRODUCT.migration.business.impl.DataMigrationServiceImpl">

      <property name="someDAO" ref="someDAO" />

      <property name="anotherDAO" ref="anotherDAO" />

      <property name="oneMoreDAO" ref="oneMoreDAO" />

      <property name="dataMigrationDAO" ref="dataMigrationDAO" />

      </bean>

      </property>

      <property name="transactionAttributes">

      <props merge="true">

      <prop key="performDataMigration">PROPAGATION_SUPPORTS</prop>

      </props>

      </property>

      </bean>

       

      The "baseTransactionProxy" reference is just a generalization of "org.springframework.transaction.interceptor.TransactionProxyFactoryBean" with default configurations and "transactionManager" property configured to use "JtaTransactionManager".

       

      Besides the collection of data executed on source system (using the source system datasource), I registrate the last date the migration was performed on it as well.

      So the service writes this date on source system and registrates lots of information on destination system using two different datasources without the configuration of XA compliant drivers; and all this works when I set the propagation to "PROPAGATION_SUPPORTS".

      If I just switch it to "PROPAGATION_REQUIRED", I get an exception.

       

      With the service running this way (i.e., no XA drivers used on any of the datasources and "PROPAGATION_SUPPORTS" configuration), I get a all or nothing execution.

      Everything is commited if nothing wrong happens or nothing commited otherwise.

       

      I have always thought that this could be acchieved only using both, or at least one, XA compliant datasource.

       

      The question: how this works?

       

      Thanks and best regards you all!

      Mauro.