JOTM을 이용한 분산Transaction 처리

 

개요

Spring 등의 오픈소스프레임워크를 이용한 개발 프레젠테이션을 할 때 질문을 받았던 내용 중에 하나가무거운 EJB보다 필요한 기능만을 갖춘 가벼운 Spring등의 프레임워크를 쓰자는 것은 이해가 간다. EJB를 쓰는 주된 이유중에 하나인 분산처리 기능을 Spring등은 어떻게 처리하고 있는가?”

교과서적인 답변이랄까? Spring JTA를 이용한 분산처리 트랜잭션API을 지원하고 있습니다. -_- a

틀린 말은 아니지만 그 분의 질문은 JTA를 어떻게 사용할수 있는가라는 의도였던 것 같다. WAS 를 쓰면서도 EJB 만의 기능(앞서 언급한 분산처리기능)을 구현하거나 필요로 했던 프로젝트는 그다지 많지 않았다. 그래서 Spring등과 톰캣을 이용한 프로젝트들이 많이 생겨난 것이지만 사실 그렇기 때문에 Spring을 통해서도 충분히 분산처리가 가능합니다.라고 고객께 말은 드리지만 정작 분산처리기능이 필요한 경우에는 특히 분산트랜잭션 서비스를 지원하지 않은 서블릿컨테이너(톰캣)을 사용하는 경우에 JTA 를 어떻게 사용해야 하는지 개발자는 조금 더 알아야 하지 않을까?

JOTM(Java Open Transaction Manager)

 

두 개 이상의 자원에 동시에 접근하는데 Transaction이 필요한 경우가 있다. 예를 들어 결재정보를 저장하는 데이터베이스와 구매내역을 저장하는 데이터베이스가 다르다고 할때 이 두 데이터베이스에 접근하기 위한 DataSource는 다르지만 두 데이터베이스에 접근하는 코드는 단일 트랜잭션으로 처리되어야 한다. 웹로직이나 JBoss 등의 WAS는 자체적으로 분산트랜잭션서비스를 지원하지만 톰캣과 같은 서블릿컨테이너는 분산 트랜잭션을 지원하지 않는다. 만약 톰캣과 같은 분산트랜잭션을 지원하지 않은 컨테이너에서 구현해야 한다면 JOTM을 사용하면된다.

 

JOTM(Java Open Transaction Manager) ObjectWeb에서 제공하는 트랜잭션 관리자로서 JTA, JTS 등의 API를 지원하고 있으며 JOTM을 사용하면 기존의 JDBC 기반의 코드에 JTA를 이용한 트랜잭션 처리 코드를 손쉽게 적용할 수 있게 된다..

아래의 항목은 Spring에서 JOTM을 어떻게 사용하는지에 대하여 설명하고 있으며 순서에 따라 진행하면 된다.

 

1. JOTM library download  Jar 파일 설치

  - spring2.5를 다운받았다면 :jotm,jotm_jrmp_stubs.jar,xapool.jar webapplication classpath에 추가

  - JOTM site에서 download받게되면 ow_carol-all.jar를 찾아 webapplication classpath에 추가

 

2.spring에서 제공하는 JotmFactoryBean bean 설정

 

3.각각 사용할 database dataSource org.enhydra.jdbc.pool.StandardXAPoolDataSource를 이용하여 설정한다

 

4.ibatis를 사용할 경우 slqMapClient에 각각 사용할 dataSource property로 가지도록 설정한다

 

spring설정 file(일반적으로 application.xml)

 

  <!-- jotm 설정 -->

    <bean id="jotm"

        class="org.springframework.transaction.jta.JotmFactoryBean" />

 

    <!-- jotm property로 가지는 JtaTransactionManager설정 -->

    <bean id="transactionManager"

        class="org.springframework.transaction.jta.JtaTransactionManager"  p:userTransaction-ref="jotm" />

    <!-- StandardXAPoolDataSource를 이용한 postgresSQL dataSource설정  -->

    <bean id="postgresDBDataSource"  class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"

destroy-method="shutdown">

        <property name="dataSource">

            <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">

                <property name="transactionManager" ref="jotm" />

                <property name="driverName" value="org.postgresql.Driver" />

                <property name="url" value="jdbc:postgresql://localhost:5432/testDb?charSet=UTF-8" />

            </bean>

        </property>

        <property name="user" value="test" />

        <property name="password" value="test" />

    </bean>

    

    <!-- StandardXAPoolDataSource를 이용한 oracle dataSource설정  -->

    <bean id="oracleDBDataSource"  class="org.enhydra.jdbc.pool.StandardXAPoolDataSource"

        destroy-method="shutdown">

        <property name="dataSource">

            <bean class="org.enhydra.jdbc.standard.StandardXADataSource" destroy-method="shutdown">

                <property name="transactionManager" ref="jotm" />

                <property name="driverName" value="oracle.jdbc.driver.OracleDriver" />

                <property name="url" value="jdbc:oracle:thin:@127.0.0.1:1526:TEST" />

            </bean>

        </property>

        <property name="user" value="test" />

        <property name="password" value="test" />

    </bean>

    

    <!-- postgresSQL dataSource property로 하는 slqMapClient설정 -->

    <bean id="sqlMapClient"  class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

       <property name="configLocation" value="/WEB-INF/config/sqlmap-config.xml"/>

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

    </bean>

    

    <!-- oracle dataSource property로 하는 slqMapClient설정 -->

    <bean id="oracleDbSqlMapClient"  class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

       <property name="configLocation" value="/WEB-INF/config/sqlmap-config.xml"/>

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

    </bean>

    

    <!-- postgresSQL dataSource property로 하는 slqMapClient를 가지는 dao -->

    <bean id="postgresDbDao" class="test.dao.PostgresDbDao">

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

    </bean>

    

    <!-- oracle dataSource property로 하는 slqMapClient를 가지는 dao -->

    <bean id="oracleDbDao" class="test.dao.OracleDbDao">

        <property name="sqlMapClient" ref="oracleDbSqlMapClient" />    

    </bean>

   <!-- The business Logic are autodetected POJOs labeled with the @Service annotaion -->

   <context:component-scan base-package="test.service" scoped-proxy="targetClass"  />

    <context:annotation-config />

    <!-- annotation으로 transcation를 선언 이때 transactionManager jotm transactionManager로 한다  -->

    <tx:annotation-driven transaction-manager="transactionManager"/>

 

iBatis 설정(일반적으로 sqlMap.xml)

 

  <insert id="insertTestInOracleDb" parameterClass="java.util.Map">

        INSERT INTO test_imsi ( name,age) VALUES (#name#,#age#)

    </insert>

    

    <insert id="insertTestInPostgresDb" parameterClass="java.util.Map">

        INSERT INTO test2_imsi ( name,age) VALUES (#name#,#age#)

    </insert>

 

dao (postgresSQL 사용, 여기서는 PostgresDbDao.java)

 

 public class PostgresDbDao extends SqlMapClientDaoSupport

{

    public void insertTestTable(Map<String,String> paramMap)

    {

        getSqlMapClientTemplate().insert("test.insertTestInPostgresDb",paramMap);

    }

}

 

dao (Oracle 사용, 여기서는 OracleDbDao.java)

 

 public class OracleDbDao extends SqlMapClientDaoSupport

{

    public void insertTestTable(Map<String,String> paramMap)

    {

        getSqlMapClientTemplate().insert("test.insertTestInOracleDb",paramMap);

    }

}

 

Service (비즈니스 로직 구현부)

 

 @Service

 @Transactional

 public class TestService

 {

    @Autowired

    private PostgresDbDao postgresDbDao;

    @Autowired

    private OracleDbDao oracleDbDao;

    

    public void jotmTransaction(Map<String,String> paramMap)

    {

        postgresDbDao.insertTestTable(paramMap);

        oracleDbDao.insertTestTable(paramMap);

    }

 }

 

 
블로그 이미지

시반

시반(詩伴)이란 함께 시를 짓는 벗이란 뜻을 가지고 있습니다. 함께 나눌수 있는 그런 공간이길 바라며...

카테고리

분류 전체보기 (233)
개발 이야기 (73)
WEB2.0 (57)
DB2 (24)
MySQL (6)
오라클 (26)
기타 (44)
취미 (0)
잡담 (2)