Announcement Announcement Module
Collapse
No announcement yet.
Transaction causing JMS to loop Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Transaction causing JMS to loop

    I'm using Spring to consume JMS messages. I've implemented the DefaultMessageListenerContainer and I'm also using the transactionManager property.
    In the onMessage method I make a call to another service call which also has the transaction annotation on it to persist the JMS message but if that service method throws an exception the message remains on the queue and tries to get reprocessed.
    I'm catching all exceptions in the onMessage method so if there are any errors processing/converting a message elsewhere the exception is caught and the next message is processed.

    Any ideas how I can have full control as to when to "acknowledge" that I have received the message even if an exception occurs.

    Thanks

  • #2
    I forgot to mention, I'm using a JDBCTransactionManager and not a JTA one if that matters?

    Comment


    • #3
      Just a fair warning, using transactions at the JMS layer is not the easiest thing, as you have to make sure that you are using a transaction oriented connection pool.

      I would take a look at the JavaDocs for org.springframework.jms.listener.AbstractMessageLi stenerContainer

      There are some notes there about the problem you are describing and how Spring handles it. By default, exceptions thrown are not exposed up to the JMS layer, and they mention a couple strategies to deal with that in those JavaDocs.

      Comment


      • #4
        Perhaps this will be clearer. And I should of added this initially, sorry.

        Code:
        <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">
            <property name="transactionManager" ref="transactionManager"/>    
            <property name="connectionFactory" ref="mqConnectionFactory"/>
            <property name="destination" ref="myMessageQueue"/>
            <property name="messageListener" ref="messageHandler"/>
          </bean>
        Code:
        <bean id="messageHandler" class="com.MessageHandler">
            <property name="anotherService" ref="marketService"/>
          </bean>
        Code:
        <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource"/>
          </bean>
        
          <tx:annotation-driven />
        Using a BasicDataSource...

        On the service method I have the
        Code:
        @Transactional(propagation = Propagation.REQUIRED)
        declared above the method I'm calling within my MessageHandler which implements MessageListener, I'm calling this service from the onMessage() method.

        In the onMessage everything is wrapped in a try block and if something happens the exception is caught and the message is removed from the queue, like I want. However if an exception occurs in my service class(transactional) which also get's called from the MessageHandler then the message isn't removed from the queue and it keeps getting processed which is the correct but undesired behavior.

        I had a look at the AbstractMessageListenerContainer and if that's the only way to go then I guess I have no choice??

        Comment


        • #5
          That propagation annotation makes sense. It might be the case that this only works with a JTA transaction manager to tie the two types of transactions together. I found a nice article on this subject that you may want to take a look at:

          http://www.javaworld.com/javaworld/j...xa.html?page=1

          Comment


          • #6
            Thanks for the info.
            I solved the problem though, I removed the transaction control from the Container, so my bean looks like this now.

            Code:
            <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer">    
                <property name="connectionFactory" ref="mqConnectionFactory"/>
                <property name="destination" ref="myMessageQueue"/>
                <property name="messageListener" ref="messageHandler"/>
              </bean>
            But I added the Transaction annotation to the onMessage method in my messageHandler class, that seems to be doing the job now.

            Thanks again

            Comment

            Working...
            X