java – JMS侦听器中异常的JMS消息重新传递

org.springframework.jms.listener.AbstractMessageListenerContainer的Javadoc说明,如果

“sessionAcknowledgeMode” set to “CLIENT_ACKNOWLEDGE”: Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.

我想,“在抛出异常的情况下没有重新传递”意味着,即使在jms监听器中抛出异常,该消息也不会被重新传递(因此,我猜,它会得到确认).但是,从侦听器抛出的异常意味着对它的调用不成功,并且由于没有确认应该重新发送.

问题是:
在jms监听器中抛出异常的情况下,消息确认实际应该发生什么?

从这个堆栈跟踪中可以看到真正发生的事情:

at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:98)
at org.springframework.jms.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:66)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:660)
at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:620)
at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:591)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:308)
at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:246)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1142)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1134)
at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:1031)

堆栈跟踪的第5行是特别感兴趣的.那里的代码基本上意味着,(大多数情况下)从侦听器抛出的任何异常都将绕过在org.springframework.jms.listener.AbstractMessageListenerContainer#commitIfNecessary中完成的ackowledgement.
没关系,但是“抛出异常时没有重新发送”意味着什么呢?

附加信息:
弹簧JMS:4.1.2

<bean id="someListenerContainerFactory" class="org.springframework.jms.config.DefaultJmsListenerContainerFactory">
    <property name="connectionFactory" ref="connectionFactory"/>
    <property name="concurrency" value="1-10"/>
    <property name="sessionAcknowledgeMode">
        <util:constant static-field="javax.jms.Session.CLIENT_ACKNOWLEDGE"/>
    </property>
</bean>
最佳答案
这取决于您使用的侦听器容器;当使用AUTO ack模式时,SimpleMessageListenerContainer会在侦听器返回后执行(即传统的JMS MessageListener). DefaultMessageListenerContainer在调用侦听器之前确定,因此您需要acknowledgeMode =“transacted”以防止消息丢失.

这个领域的javadocs有点误导,已经有improved recently了.

使用CLIENT_ACKNOWLEDGE,您可以自行完成任务.那个doc只是意味着你是经纪人的心血来潮.根据JMS消息javadoc:

Messages that have been received but not acknowledged may be redelivered

根据我的经验,最好使用带有SMLC的auto ack和使用DMLC的事务.

转载注明原文:java – JMS侦听器中异常的JMS消息重新传递 - 代码日志