Results 1 to 10 of 21

Thread: Standalone JTA (Bitronix) + JPA (XA) JDBC + JPA JMS MDP (XA) ActiveMQ

Threaded View

  1. #1
    Join Date
    Dec 2008
    Posts
    9

    Arrow Standalone JTA (Bitronix) + JPA (XA) JDBC + JPA JMS MDP (XA) ActiveMQ

    Attached is standalone code that sets up and tests XA 2-phase commit on two transactional resources through JTA (using Bitronix Transaction Manager).

    The two resources are (a) an embedded Derby database accessed via an XA aware JDBC connection (b) an embedded ActiveMQ JMS queue accessed via Spring Message Driven Pojo (MDP).

    The library versions used are:

    * org.codehaus.btm:btm:1.3
    * org.apache.derby:derby:10.4.2.0
    * org.springframework:spring:2.5.6
    * activemq:activemq-core:3.2.4

    The spring configuration is:

    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="ht tp://ww w.springframework.org/schema/beans"
    	xmlns:xsi="ht tp://ww w.w3.org/2001/XMLSchema-instance" xmlns:tx="ht tp://ww w.springframework.org/schema/tx"
    	xmlns:p="ht tp://ww w.springframework.org/schema/p" xmlns:util="ht tp://ww w.springframework.org/schema/util"
    	xsi:schemaLocation="
    	ht tp://ww w.springframework.org/schema/beans ht tp://ww w.springframework.org/schema/beans/spring-beans.xsd
        ht tp://ww w.springframework.org/schema/tx ht tp://ww w.springframework.org/schema/tx/spring-tx.xsd
        ht tp://w ww.springframework.org/schema/util ht tp://w ww.springframework.org/schema/util/spring-util-2.0.xsd
    	">
    	
    	<description>
    	This file defines a Bitronix Transaction Manager (BTM), a Spring Message Driven Pojo (MDP), and a JDBC DAO. 
    	</description>
    	
    	<!-- Bitronix Transaction Manager embedded configuration -->
    	<bean id="btmConfig" factory-method="getConfiguration"
    		class="bitronix.tm.TransactionManagerServices">
    		<property name="serverId" value="spring-btm" />
    	</bean>
    
    	<!-- Create the BTM transaction manager -->
    	<bean id="BitronixTransactionManager" factory-method="getTransactionManager"
    		class="bitronix.tm.TransactionManagerServices" depends-on="btmConfig,xaDataSource"
    		destroy-method="shutdown" />
    
    	<!-- Spring JtaTransactionManager -->
    	<bean id="jtaTransactionManager"
    		class="org.springframework.transaction.jta.JtaTransactionManager">
    		<property name="transactionManager" ref="BitronixTransactionManager" />
    		<property name="userTransaction" ref="BitronixTransactionManager" />
    	</bean>
    
    	<!-- XA DataSource -->
    	<bean id="xaDataSource" class="bitronix.tm.resource.jdbc.PoolingDataSource"
    		init-method="init" destroy-method="close">
    		<property name="className" value="org.apache.derby.jdbc.EmbeddedXADataSource" />
    		<property name="uniqueName" value="derby1" />
    		<property name="minPoolSize" value="0" />
    		<property name="maxPoolSize" value="3" />
    		<property name="driverProperties">
    			<props>
    				<prop key="databaseName">derbydb</prop>
    				<prop key="createDatabase">create</prop>
    			</props>
    		</property>
    	</bean>
    
    	<!-- Raw untransactional DAO  -->
    	<bean id="messageSequenceDaoImpl" class="com.acme.springjta.jdbc.MessageSequenceDaoImpl">
    		<property name="dataSource" ref="xaDataSource" />
    	</bean>
    	
    	<!-- Transactional wrapper of the DAO -->
    	<bean id="messageSequenceDAO"
    		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager" ref="jtaTransactionManager" />
    		<property name="transactionAttributes">
    			<props>
    				<prop key="*">PROPAGATION_REQUIRED, -Exception
    				</prop>
    			</props>
    		</property>
    		<property name="target" ref="messageSequenceDaoImpl" />
    	</bean>
    
    	<!-- XA JMS Connection Factory -->
    	<bean id="xaJmsConnectionFactory" class="bitronix.tm.resource.jms.PoolingConnectionFactory"
    		init-method="init" destroy-method="close">
    		<property name="className" value="org.activemq.ActiveMQXAConnectionFactory" />
    		<property name="uniqueName" value="activemq" />
    		<property name="minPoolSize" value="1" />
    <!-- you would want a bigger pool and look to tune the number of threads working with ActiveMQ! -->
    		<property name="maxPoolSize" value="1" />
    		<property name="allowLocalTransactions" value="true" />
    		<property name="user" value="user" />
    		<property name="password" value="password" />
    		<property name="driverProperties">
    			<props>
    				<prop key="brokerURL">vm://localhost</prop>
    			</props>
    		</property>
    	</bean>
    
    	<!-- JMS Destination -->
    	<bean id="destination" class="org.activemq.message.ActiveMQQueue">
    		<constructor-arg value="test.queue" />
    	</bean>
    
    	<!-- JMS Template for sending messages -->
    	<bean id="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
    		<property name="connectionFactory" ref="xaJmsConnectionFactory" />
    		<property name="defaultDestination" ref="destination" />
    	</bean>
    
    	<!-- Service for sending JMS messages -->
    	<bean id="defaultTextMessageSender" class="com.acme.springjta.mdp.DefaultTextMessageSender">
    		<property name="jmsTemplate" ref="jmsTemplate" />
    	</bean>
    
    	<!-- Transactional wrapper of the service for sending JMS message -->
    	<bean id="textMessageSender"
    		class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
    		<property name="transactionManager" ref="jtaTransactionManager" />
    		<property name="transactionAttributes">
    			<props>
    				<prop key="*">PROPAGATION_REQUIRED, -Exception
    				</prop>
    			</props>
    		</property>
    		<property name="target" ref="defaultTextMessageSender" />
    	</bean>
    
    	<!-- Our Message Driven POJO. Normally such a MDP would have an injected DataSource or injected DAO -->
    	<bean id="textMessageDelegate" class="com.acme.springjta.mdp.DefaultTextMessageDelegate" />
    
    	<!-- JMS Listener Delegates to our Message Driven POJO -->
    	<bean id="messageListener"
    		class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
    		<constructor-arg ref="textMessageDelegate" />
    		<property name="defaultListenerMethod" value="receive" />
    		<!-- we don't want automatic message context extraction -->
    		<property name="messageConverter">
    			<null />
    		</property>
    	</bean>
    
    	<!-- JMS Container For Receiving Messages Under XA -->
    	<bean id="jmsContainer"
    		class="org.springframework.jms.listener.DefaultMessageListenerContainer">
    		<property name="connectionFactory" ref="xaJmsConnectionFactory" />
    		<property name="destination" ref="destination" />
    		<property name="messageListener" ref="messageListener" />
    		<property name="transactionManager" ref="jtaTransactionManager" />
    	</bean>
    </beans>
    The code is built by maven and only the "test" goal is implemented. To build and run the sample:

    1) download and extract a maven2 distribution
    2) set an environment variable "MAVEN_HOME" to name the absolute path of the unzipped maven2 folder
    3) set an environment variable "JAVA_HOME" to name the absolute path of the top level of your Java1.5+ JDK folder
    4) prepend the "bin" subfolders of both "MAVEN_HOME" and "JAVA_HOME" to your "PATH"
    5) open up a shell (cmd.exe on windows else bash on un1x) and "cd" into the folder of the extracted sample app code
    6) run the command "mvn test". maven should pull down all dependent jar files and run the unit tests.

    Alternatively if you are using eclipse you can simply install the m2eclipse plug-in and just import the extracted zip as a project in your workspace. The simply right click on the project and choose "Run As..." > "maven test".
    Attached Files Attached Files

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •