Announcement Announcement Module
Collapse
No announcement yet.
JMS: JTA transaction problems with DefaultMessageListenerContainer Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JMS: JTA transaction problems with DefaultMessageListenerContainer

    I'm using JMS with GlassFish application server v2, and Spring 2.5.5. I want to read JMS messages with concurrent consumers, so I use the DefaultMessageListenerContainer, but I have some errors on the console (althougn the consumption of messages works fine):
    Code:
    endTransaction (XA) on JMSService:jmsdirect failed for connectionId:6762471324442619392 and flags=67108864 due to unkown JMSService server error.
    RAR5031 : Exception système.
    javax.transaction.SystemException
            at com.sun.jts.jta.TransactionImpl.delistResource(TransactionImpl.java:250)
            at com.sun.enterprise.distributedtx.J2EETransaction.delistResource(J2EETransaction.java:548)
            at com.sun.enterprise.distributedtx.J2EETransactionManagerImpl.delistResource(J2EETransactionManagerImpl.java:833)
            at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.delistResource(J2EETransactionManagerOpt.java:229)
            at com.sun.enterprise.resource.ResourceManagerImpl.unregisterResource(ResourceManagerImpl.java:265)
            at com.sun.enterprise.resource.ResourceManagerImpl.delistResource(ResourceManagerImpl.java:223)
            at com.sun.enterprise.resource.PoolManagerImpl.resourceClosed(PoolManagerImpl.java:400)
            at com.sun.enterprise.resource.ConnectorAllocator$ConnectionListenerImpl.connectionClosed(ConnectorAllocator.java:72)
            at com.sun.messaging.jms.ra.ConnectionEventListener.sendEvent(ConnectionEventListener.java:143)
            at com.sun.messaging.jms.ra.ManagedConnection.sendEvent(ManagedConnection.java:675)
            at com.sun.messaging.jms.ra.DirectConnection.close(DirectConnection.java:231)
            at org.springframework.jms.connection.ConnectionFactoryUtils.releaseConnection(ConnectionFactoryUtils.java:81)
            at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:357)
            at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:240)
            at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:944)
            at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:868)
            at java.lang.Thread.run(Thread.java:619)

    I found a workaround to remove these errors: I set the transactionSynchronizationName property of the jtaTransactionManager to SYNCHRONIZATION_NEVER, and I modified the AbstractPollingMessageListenerContainer to commit the transaction before the call of ConnectionFactoryUtils.releaseConnection (I removed the transactionManager.commit statement from the receiveAndExecute method, and I put it before the 2 return statements of the method doReceiveAndExecute).
    But I hope there is a better solution, I wonder if I misconfigured something.

    I have an other problem: on my MessageListener, I rollback the transaction by using transactionManager.rollback(transaction); but if I use transaction.setRollbackOnly(); the transaction is not rollbacked. I want to use this method to avoid these errors:
    Code:
    [jmsContainer-3] ERROR DefaultMessageListenerContainer - Listener exception overridden by rollback exception
    org.springframework.transaction.UnexpectedRollbackException: JTA transaction unexpectedly rolled back (maybe due to a timeout); nested exception is javax.transaction.RollbackException
            at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1031)
            at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
            at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
            at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:330)
            at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:227)
            at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:932)
            at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:856)
            at java.lang.Thread.run(Thread.java:619)
    Caused by: javax.transaction.RollbackException
            at com.sun.jts.jta.TransactionManagerImpl.commit(TransactionManagerImpl.java:311)
            at com.sun.enterprise.distributedtx.J2EETransactionManagerImpl.commit(J2EETransactionManagerImpl.java:1030)
            at com.sun.enterprise.distributedtx.J2EETransactionManagerOpt.commit(J2EETransactionManagerOpt.java:397)
            at com.sun.enterprise.distributedtx.UserTransactionImpl.commit(UserTransactionImpl.java:197)
            at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1028)
            ... 7 more
    Here is my configuration:
    HTML Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <beans>
        <!--ConnectionFactory and queue.-->
        <bean id="jmsQueueConnectionFactory" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiTemplate">
                <ref bean="jndiTemplate"/>
            </property>
            <property name="jndiName">
                <value>jms/myQueueConnectionFactory</value>
            </property>
        </bean>
        <bean id="queue" class="org.springframework.jndi.JndiObjectFactoryBean">
            <property name="jndiTemplate">
                <ref bean="jndiTemplate"/>
            </property>
            <property name="jndiName">
                <value>myQueue</value>
            </property>
        </bean>
        <bean id="jndiTemplate" class="org.springframework.jndi.JndiTemplate"/>
        <!--Listener-->
        <bean id="messageListener" class="testjmsreceiver.MessageListenerConsumer">
            <constructor-arg>
                <ref bean="jtaTransactionManager"/>
            </constructor-arg>
        </bean>
        <bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="connectionFactory" ref="jmsQueueConnectionFactory"/>
            <property name="destination" ref="queue"/>
            <property name="messageListener" ref="messageListener" />
            <property name="concurrentConsumers" value="2" />
            <property name="maxConcurrentConsumers" value="2" />
            <property name="transactionManager" ref="jtaTransactionManager" />
        </bean>
        <bean id="jtaTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
            <property name="transactionSynchronizationName" value="SYNCHRONIZATION_NEVER"/>
        </bean>
    </beans>
    and my MessageListener:
    PHP Code:
    package testjmsreceiver;
    import java.util.Random;
    import javax.jms.*;
    import org.slf4j.*;
    import org.springframework.transaction.PlatformTransactionManager;
    public class 
    MessageListenerConsumer implements MessageListener {
        static final 
    Logger logger LoggerFactory.getLogger(MessageListenerConsumer.class);
        private final 
    PlatformTransactionManager transactionManager;
        public 
    MessageListenerConsumer(PlatformTransactionManager transactionManager) {
            
    this.transactionManager transactionManager;
        }
        public 
    void onMessage(Message msg) {
            try {
                
    TextMessage message = (TextMessagemsg;
                
    String text message.getText();
                
    int sleepTime = new Random().nextInt(25000);
                
    logger.info("Received message {}. Sleeping {}s"textsleepTime 1000);
                
    Thread.sleep(sleepTime);
                if (new 
    Random().nextInt(5) == 0) {
                    
    logger.info("Message {}: rollback"text);
                    
    transactionManager.rollback(transactionManager.getTransaction(null));
    //                transactionManager.getTransaction(null).setRollbackOnly();//Does not work
                
    } else {
                    
    logger.info("Message {}: commit"text);
                }
            } catch (
    Exception ex) {
                
    logger.error("error"ex);
            }
        }

Working...
X