JMS在onMessage

问题描述

我有一个JMS 2.0 MessageListener,即使已成功处理了消息(通过日志确认),它似乎也会偶尔重新处理消息。我怀疑需要完成session.commit(),但是我不确定,因为在大多数情况下,不会重试消息。据我了解,AUTO_ACKNowLEDGE是认设置,但同样,我不确定它如何用于SessionAwareMessageListener。

相关的spring.xml部分看起来像这样

<bean id="jmsContainer" class="org.springframework.jms.listener.DefaultMessageListenerContainer">
        :
        :
        <property name="messageListener" ref="myMessageListener" />
        <property name="maxConcurrentConsumers" value="1" />
        <property name="receiveTimeout" value="5000" />
        <property name="sessionTransacted" value="true" />
    </bean>

MessageListener的实现如下

public class MyMessageListener implements SessionAwareMessageListener {

   // All spring autowired objects
   :
   :
   @Override
   public void onMessage(Message message,Session session)
   {
     logger.debug("JMSMessage ID : " + message.JMSMessageId,"Entering onMessage() ...");
     logger.debug("JMSMessage ID : " + message.JMSMessageId,"Retry Count : " + message.getIntProperty("JMSXDeliveryCount"));
     try
     {
     
     }
     catch(JMSException e)
     {
        // Log something 
        throw new RuntimeException(e);
     }
     catch(Exception ex)
     {
        if(certain types of exceptions)
        {
          session.rollback();
          System.Exit(1);
        }
        
        throw new RuntimeException(ex);

     }
     // THE FOLLOWING IS THE LAST LINE IN onMessage()
     logger.debug("JMSMessage ID : " + message.JMSMessageId,"Completed successfully !");

   }


}

所以,我现在看到的几乎所有消息都在日志​​中有

:
JMSMessage Id : 1234,Entering onMessage()
JMSMessage Id : 1234,Retry count : 1
:
JmsMessage Id : 1234,Completed successfully!
JmsMessage Id : 3344,Entering onMessage() // New message taken up for processing.
JMSMessage Id : 3344,Retry count : 1

问题在于,有时(在成千上万条消息之后),我会在日志中看到这一点

:
JMSMessage Id : 5566,Entering onMessage()
JMSMessage Id : 5566,Retry count : 1
:
JmsMessage Id : 5566,Completed successfully!
JMSMessage Id : 5566,Entering onMessage() // WHY IS JMS PROCESSING THE SAME MESSAGE (MESSAGEID : 5566) AGAIN ?
JMSMessage Id : 5566,Retry count : 2 
:
:

解决方法

当您将sessionTransacted设置为true时,忽略确认模式,甚至可以设置一个特殊值来表示它未被使用,从其他示例中可以看到:

<property name="sessionAcknowledgeModeName" value="SESSION_TRANSACTED"/>

根据Gary Russell对stackoverflow问题Spring DMLC message consumption: auto_ack vs Transacted Session的回答,如果您将DMLC的sessionTransacted设置为true,则在调用侦听器后,如果侦听器抛出异常,则由DMLC提交会话交易回滚的异常。