2015-04-02 101 views
2

的Javadoc org.springframework.jms.listener.AbstractMessageListenerContainer狀態,如果JMS消息交還

「SessionAcknowledgeMode來」設置爲「CLIENT_ACKNOWLEDGE」:成功的聽者執行後自動消息確認;在拋出異常情況下無法重新投遞。

我猜「在例外的情況下,不交還拋出」手段,該消息不會交還(所以,我的猜測,這將是確認的),即使是在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中完成的回覆。
沒關係,但「沒有再次發生異常情況下拋出」是什麼意思呢?

附加信息:
彈簧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> 

回答

3

這取決於你使用的監聽器容器;當使用自動確認模式時,聽衆返回後SimpleMessageListenerContainer確認(即傳統的JMS MessageListener)。在偵聽器被調用之前,它需要DefaultMessageListenerContainer,所以你需要acknowledgeMode="transacted"來防止消息丟失。

在這方面的javadocs有點誤導,並已improved recently

有了CLIENT_ACKNOWLEDGE,你就可以自己動手了。該文件只是意味着你正處於經紀人的心血結晶之中。根據JMS消息的javadoc:已收到但尚未確認

的消息可重新傳遞

以我的經驗,最好是使用自動應答與SMLC的交易而與DMLC

+0

我明白了,但CLIENT_ACKNOWLEDGE沒有任何變化。 我正在使用'DefaultMessageListenerContainer'。 而且,通過javadocs,'CLIENT_ACKNOWLEDGE'意味着容器將在成功偵聽器執行後爲我執行* * – borodust 2015-04-02 18:46:27

+0

否; 'CLIENT_ACKNOWLEDGE'表示你負責調用'Message.acknowledge()'。閱讀JMS規範。 – 2015-04-02 21:41:48

+0

我不是在問JMS規範,而是在春天的容器行爲。如果你看看'org.springframework.jms.listener.AbstractMessageListenerContainer#commitIfNecessary',你可以清楚地看到,它在偵聽器執行後自動確認我。無論這是否是正確的行爲是不可能的,因爲容器javadoc明確地說明了這一點。 – borodust 2015-04-03 10:01:20