有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

Javadoc for org.springframework.jms.listener.AbstractMessageListenerContainer声明,如果

"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)

stacktrace的第5行特别有趣。那里的代码基本上意味着(大多数情况下)从侦听器抛出的任何异常都将绕过在org.springframework.jms.listener.AbstractMessageListenerContainer#commitIfNecessary中完成的ackowledget
没关系,但是“在抛出异常的情况下不重新交付”意味着什么

其他信息:
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) 个答案

  1. # 1 楼答案

    这取决于您使用的侦听器容器;使用自动确认模式时,SimpleMessageListenerContainer在侦听器返回后确认(即传统的JMSMessageListener)。在调用侦听器之前DefaultMessageListenerContainer会确认,因此需要acknowledgeMode="transacted"来防止消息丢失

    这个领域的Javadoc有点误导,而且一直是improved recently

    有了客户确认,你就可以自己做确认了。那个医生的意思是你是在经纪人的一时兴起。根据JMS消息javadoc:

    Messages that have been received but not acknowledged may be redelivered

    根据我的经验,最好使用带有SMLC的自动确认和带有DMLC的事务