Announcement Announcement Module
Collapse
No announcement yet.
ActiveMQ, XA tranasctions, database Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • ActiveMQ, XA tranasctions, database

    Hello,

    Has anyone successfully managed to configure a JEE-free Spring application that makes use of ActiveMQ XA tranasctions? ie the use cases are:

    1. When a message is read and a database exception thrown when writing to the database, the message is rolled back onto the queue.
    2. If ActiveMQ fails whilst the message is being processed, even if a database insert statement has been issued, the database transaction is rolled back because the message can not be confirmed as processed?

    I've got a Spring application working with (1) but I can't meet (2). I didn't need XA for (1) and I'm assuming XA is required for (2). Maybe I'm wrong.

    The ActiveMQXAConnectionFactory does not seem well documented in terms of examples, etc. Here's a subset of what I've got to meet (1):

    Code:
    	<bean id="connectionFactory" class="org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy">
    		<property name="synchedLocalTransactionAllowed" value="true" />
    		<property name="targetConnectionFactory"><bean class="org.apache.activemq.pool.PooledConnectionFactory"
    			destroy-method="stop">			
    			<property name="connectionFactory">
    				<bean class="org.apache.activemq.ActiveMQConnectionFactory">
    					<property name="dispatchAsync" value="false" />
    					<property name="brokerURL" value="${jms.brokerurl}" />
    					<property name="userName" value="${jms.user}" />
    					<property name="password" value="${jms.password}" />						  
    					<property name="redeliveryPolicy" ref="jms.redeliveryPolicy" />	
    				</bean>
    			</property>
    		</bean></property>
    	</bean>	
    
    	<bean id="jms.transactionManager"
    			class="org.springframework.jms.connection.JmsTransactionManager">
    		<property name="connectionFactory" ref="connectionFactory" />
    	</bean>
    However when I introduced the ActiveMQXAConnectionFactory, I need to use the XaPooledConnectionFactory however this requires a reference to the transaction manager - and this can not be created until the connection factory has been created.

    Does anyone have any inspiration to share?

    Thanks


    John

  • #2
    Stepping through with a debugger, the problem appears to be that the database transaction is committed before the JMS session is committed (and message removed). So the question is, how do I tie up the DB transaction with the session commit?

    Comment


    • #3
      XA is expensive; with careful coding (such as handling duplicate messages as would happen with your second scenario), you can avoid the overhead of using XA.

      See http://www.javaworld.com/javaworld/j...nsactions.html for a complete discussion of the options.

      If you have no choice but to use XA, and you are running outside of a JEE container, you need to use an XA-capable transaction manager such as Atomikos or jotm.

      Comment


      • #4
        Originally posted by Gary Russell View Post
        If you have no choice but to use XA, and you are running outside of a JEE container, you need to use an XA-capable transaction manager such as Atomikos or jotm.
        Thanks. I was just reading upon Atomikos.

        Comment


        • #5
          Originally posted by jbakerc View Post
          Thanks. I was just reading upon Atomikos.
          Does anyone know of a good guide covering linking JMS and JPA within Atomikos, that would cover something like this in Spring:

          Code:
          <bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
          
          <bean id="remoteDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
          	  destroy-method="close">
          	...
          </bean>
          
          <bean id="remoteJPAAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" 
          	  p:database="..." 
          	  p:showSql="..."/>
          
          <bean id="remotePersistenceUnitManager" class="org.springframework.data.jpa.support.MergingPersistenceUnitManager">
          	<property name="persistenceXmlLocations">
          		<list>
          			<value>classpath*:META-INF/*/persistence.xml</value>
          		</list>
          	</property>
          	<property name="dataSources">
          		<map>
          			<!-- keyed from persistence.xml -->
          			<entry key="remoteDS" value-ref="remoteDataSource"/>
          		</map>
          	</property>
          	<!-- if no datasource is specified, use this one -->
          	<property name="defaultDataSource" ref="remoteDataSource"/>
          </bean>
          
          <bean id="remoteEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
          	p:jpaVendorAdapter-ref="remoteJPAAdapter">
          	<property name="persistenceUnitManager" ref="remotePersistenceUnitManager"/>
          </bean>
          
          <bean id="remoteTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
          	<property name="entityManagerFactory" ref="remoteEntityManagerFactory" />
          </bean>
          I've tried and it runs but Hibernate is pushing a row into the database when the persist method on the entity manager is called, as if XA wasn't in use at all - at least it used to do this after the @Transactional annotated method completed.

          Comment


          • #6
            Take a look a Josh Long's blog post, referenced in this thread.... http://forum.springsource.org/showth...s-using-Spring

            He uses JavaConfig rather than XML, but it's effectively the same.

            Also, be sure to use XA-aware drivers for the resources.

            Comment

            Working...
            X