JMS message redelivery on exception in JMS listener

左心房为你撑大大i 提交于 2019-12-01 04:56:41

问题


Javadoc for org.springframework.jms.listener.AbstractMessageListenerContainer states, that if

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

I guess, "no redelivery in case of exception thrown" means, that message would not be redelivered (so, my guess, it would be acknowledged), even if there's an exception thrown in the jms listener. But, well, exception thrown from listener means that call to it wasn't successful, and there should be redelivery due to no acknowledgement.

The question is:
What actually should happen with message acknowledgement in case of exception thrown in the jms listener?

What really happens, might be seen from this stacktrace:

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)

Line 5 of the stacktrace is of particular interest. Code there basically means, that (mostly) whatever exception thrown from the listener will bypass the ackowledgement which is done in org.springframework.jms.listener.AbstractMessageListenerContainer#commitIfNecessary.
That's ok, but what does "no redelivery in case of exception thrown" mean then?

Additional info:
spring-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>

回答1:


It depends on which listener container you use; when using AUTO ack mode, the SimpleMessageListenerContainer acks after the listener returns (i.e. a traditional JMS MessageListener). The DefaultMessageListenerContainer acks before the listener is invoked, so you need acknowledgeMode="transacted" to prevent message loss.

The javadocs in this area were a bit misleading and have been improved recently.

With CLIENT_ACKNOWLEDGE, you're on your own to do the acks. That doc just means you are at the whim of the broker. According to the JMS message javadoc:

Messages that have been received but not acknowledged may be redelivered

In my experience it is best to use auto ack with an SMLC and transactions with DMLC.



来源:https://stackoverflow.com/questions/29413784/jms-message-redelivery-on-exception-in-jms-listener

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!