Atomikos TransactionsEssentials で JTA (Spring + JDBC 編)

TransactionsEssentials は、Atomikos のフリーの JTA 実装です。

とりあえずインストールしてみた。

サイトからダウンロードして、dist フォルダから必要な jar ファイルを選び、クラスパスに通します。


とりあえず、以下の jar があれば、最低限の JDBC 操作は行えます。

  • transactions-jta.jar
  • transactions-jdbc.jar
  • transactions-api.jar
  • atomikos-util.jar
  • transactions.jar

SpringFramework で適当に定義してみた。

環境は、MySQLインスタンスを2つ用意してみました。

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

  <!-- ひとつめのデータソース -->
  <bean
    id="dataSource1"
    class="com.atomikos.jdbc.AtomikosDataSourceBean"
    init-method="init"
    destroy-method="close">
    <property name="uniqueResourceName" value="dataSource1" />
    <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
    <property name="xaProperties">
      <props>
        <prop key="user">root</prop>
        <prop key="password"></prop>
        <prop key="url">jdbc:mysql://localhost:3307/test</prop>
      </props>
    </property>
  </bean>
  
  <!-- ふたつめのデータソース -->
  <bean
    id="dataSource2"
    class="com.atomikos.jdbc.AtomikosDataSourceBean"
    init-method="init"
    destroy-method="close">
    <property name="uniqueResourceName" value="dataSource2" />
    <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource" />
    <property name="xaProperties">
      <props>
        <prop key="user">root</prop>
        <prop key="password"></prop>
        <prop key="url">jdbc:mysql://localhost:3308/test</prop>
      </props>
    </property>
  </bean>

  <!-- Atomikos の TransactionManager 実装 -->
  <bean
    id="atomikosTransactionManager"
    class="com.atomikos.icatch.jta.UserTransactionManager"
    init-method="init"
    destroy-method="close">
    <property name="forceShutdown" value="true" />
  </bean>

</beans>

commit してみた。

JdbcExample1.java
package sample;

import java.sql.Connection;
import java.sql.Statement;

import javax.sql.DataSource;
import javax.transaction.TransactionManager;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Sample for Atomikos TransactionsEssentials.
 * 
 * @author beyondseeker@users.sourceforge.jp
 * @version $Id$
 */
public class JdbcExample1 {
    
    public static void main(String[] args) throws Exception {
        
        // Create application context.
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        
        // Prepare for using
        DataSource dataSource1 = (DataSource) ctx.getBean("dataSource1");
        DataSource dataSource2 = (DataSource) ctx.getBean("dataSource2");
        TransactionManager tm = (TransactionManager) ctx.getBean("atomikosTransactionManager");
        
        // JDBC Example for XA Commit.
        tm.begin();
        
        Connection connection1 = dataSource1.getConnection();
        Statement st1 = connection1.createStatement();
        st1.executeUpdate("insert into a () values ()");
        
        Connection connection2 = dataSource2.getConnection();
        Statement st2 = connection2.createStatement();
        st2.executeUpdate("insert into a () values ()");
        
        tm.commit();
    }
    
}
dataSource1 のログ
Query       XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
Query       insert into a () values ()
Query       XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
Query       XA PREPARE 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
Query       XA COMMIT 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
dataSource2 のログ
Query       XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
Query       insert into a () values ()
Query       XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
Query       XA PREPARE 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
Query       XA COMMIT 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303033,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d


ちゃんと2フェーズコミットできてますね。 (`・ω・´)

rollback してみた。

JdbcExample2.java
package sample;

import java.sql.Connection;
import java.sql.Statement;

import javax.sql.DataSource;
import javax.transaction.TransactionManager;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Sample for Atomikos TransactionsEssentials.
 * 
 * @author beyondseeker@users.sourceforge.jp
 * @version $Id$
 */
public class JdbcExample2 {
    
    public static void main(String[] args) throws Exception {
        
        // Create application context.
        ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
        
        // Prepare for using
        DataSource dataSource1 = (DataSource) ctx.getBean("dataSource1");
        DataSource dataSource2 = (DataSource) ctx.getBean("dataSource2");
        TransactionManager tm = (TransactionManager) ctx.getBean("atomikosTransactionManager");
        
        // JDBC Example for XA Rollback.
        tm.begin();
        
        Connection connection1 = dataSource1.getConnection();
        Statement st1 = connection1.createStatement();
        st1.executeUpdate("insert into a () values ()");
        
        Connection connection2 = dataSource2.getConnection();
        Statement st2 = connection2.createStatement();
        st2.executeUpdate("insert into a () values ()");
        
        tm.rollback();
    }
    
}
dataSource1 のログ
Query       XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
Query       insert into a () values ()
Query       XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
Query       XA ROLLBACK 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d31,0x41544f4d
dataSource2 のログ
Query       XA START 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
Query       insert into a () values ()
Query       XA END 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d
Query       XA ROLLBACK 0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d30303030313030303031,0x636f6d2e61746f6d696b6f732e737072696e672e6a6462632e746d32,0x41544f4d


ちゃんとロールバックできてますね。 (`・ω・´)


Atomikos TransactionsEssentials で JTA (XA with MySQL編)に続く