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

  • ActiveMQ, XA tranasctions, database


    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):

    	<bean id="connectionFactory" class="org.springframework.jms.connection.TransactionAwareConnectionFactoryProxy">
    		<property name="synchedLocalTransactionAllowed" value="true" />
    		<property name="targetConnectionFactory"><bean class="org.apache.activemq.pool.PooledConnectionFactory"
    			<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 id="jms.transactionManager"
    		<property name="connectionFactory" ref="connectionFactory" />
    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?



  • #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?


    • #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 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.


      • #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.


        • #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:

          <bean class=""/>
          <bean id="remoteDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
          <bean id="remoteJPAAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter" 
          <bean id="remotePersistenceUnitManager" class="">
          	<property name="persistenceXmlLocations">
          	<property name="dataSources">
          			<!-- keyed from persistence.xml -->
          			<entry key="remoteDS" value-ref="remoteDataSource"/>
          	<!-- if no datasource is specified, use this one -->
          	<property name="defaultDataSource" ref="remoteDataSource"/>
          <bean id="remoteEntityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean" 
          	<property name="persistenceUnitManager" ref="remotePersistenceUnitManager"/>
          <bean id="remoteTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
          	<property name="entityManagerFactory" ref="remoteEntityManagerFactory" />
          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.


          • #6
            Take a look a Josh Long's blog post, referenced in this thread....

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

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