2012-02-01 33 views
11

剛開始讓我的頭在JMS ActiveMQ Acknowledgements在春季工作。到目前爲止,我有一位消費者完美地工作,除了當我不承認消息時,它仍然從隊列中取出(我期望它留在那裏或以死信隊列結束)。獲取一個簡單的Spring JMS客戶端確認工作

<beans xmlns="http://www.springframework.org/schema/beans" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
     xmlns:jms="http://www.springframework.org/schema/jms" 
     xmlns:p="http://www.springframework.org/schema/p" 
     xsi:schemaLocation=" 
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
http://www.springframework.org/schema/jms http://www.springframework.org/schema/jms/spring-jms-3.0.xsd"> 

    <!-- A JMS connection factory for ActiveMQ --> 
    <bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory" 
    p:brokerURL="failover://(tcp://jms1:61616,tcp://jms2:61616)?randomize=false&amp;jms.redeliveryPolicy.maximumRedeliveries=5" /> 

    <!-- A POJO that implements the JMS message listener --> 
    <bean id="simpleMessageListener" class="com.company.ConsumerClass" /> 

    <!-- A JMS namespace aware Spring configuration for the message listener container --> 
    <jms:listener-container 
      container-type="default" 
      connection-factory="connectionFactory" 
      acknowledge="client" 
      concurrency="10-50" 
      cache="consumer"> 
     <jms:listener destination="someQueue" ref="simpleMessageListener" method="onMessage" /> 
    </jms:listener-container> 
</beans> 

在ConsumerClass,我簡單的消費看起來是這樣的:

@Override public final void onMessage(Message message) { 
    Object postedMessage = null; 
    try { 
     postedMessage = ((ObjectMessage) message).getObject(); 

     if (postedMessage.getClass() == SomeMessageType.class) { 
      try { 
       //Some logic here 

       message.acknowledge(); 
       return; //Success Here 
      } catch (MyException e) { 
       logger.error("Could not process message, but as I didn't call acknowledge I expect it to end up in the dead message queue"); 
      } 
     } 
    } catch (JMSException e) { 
     logger.error("Error occurred pulling Message from Queue", e); 
    } 

    //Also worth noting, if I throw new RuntimeException("Aww Noos"); here then it won't take it from the queue, but it won't get consumed (or end up as dead letter)... 
} 

回答

-2

在我的實踐客戶端確認幾乎從不使用。典型的設置是自動確認,所以如果你的代碼通常從onMessage()返回(沒有異常),則消息被自動確認。如果您的代碼從onMessage()拋出異常,則沒有確認,並且通常會將消息重新遞送至預配置次數,之後通常將其丟棄或放入死信息隊列中。

就你而言,從JMS服務器的角度來看,它看起來像客戶端要求的消息,但從來沒有承認,所以它仍然是由客戶端處理。在這種情況下,消息對於同一隊列中的其他消費者將是不可見的,因此您可能會得到這樣的印象:消息被「排隊」,而事實上它仍然存在。顯然你不會在死信息隊列中看到這樣的信息。

我建議你閱讀JMS規範,以便清楚地瞭解不同的確認模式。

+0

對不起,在這種情況下它是成功的,如果我的message.acknowledge後返回()(我加入這個代碼示例) – 2012-02-01 21:39:11

+0

另外,如果我去掉了拋RuntimeException的(它必須運行,以滿足MessageListener接口)我收到一個錯誤: 08:39:59,066 WARN org.springframework.jms.listener.DefaultMessageListenerContainer#0-2 listener.DefaultMessageListenerContainer:694 - JMS消息偵聽器的執行失敗,並且沒有設置ErrorHandler。 java.lang.RuntimeException:Aww Noos 我可以看到,在這種情況下,消息持有消費者,直到我終止它,在這一點上,他們會試圖消費另一位消費者,讓我認爲承認=「客戶端「不執行任何操作 – 2012-02-01 21:44:17

+1

實際上,如果我讀取了javadoc權限,」auto「將在調用偵聽器之前確認: 」sessionAcknowledgeMode「設置爲」AUTO_ACKNOWLEDGE「(默認值):偵聽器執行前的自動消息確認;在拋出異常情況下不會重新傳遞。「 – dstibbe 2013-12-20 11:25:47

15

閱讀本文件:Spring的JMS的容器不使用message.acknowledge()

監聽器容器提供了以下消息確認選項:

"sessionAcknowledgeMode" set to "AUTO_ACKNOWLEDGE" (default): Automatic message acknowledgment before listener execution; no redelivery in case of exception thrown.
"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE": Automatic message acknowledgment after successful listener execution; no redelivery in case of exception thrown.
"sessionAcknowledgeMode" set to "DUPS_OK_ACKNOWLEDGE": Lazy message acknowledgment during or after listener execution; potential redelivery in case of exception thrown.
"sessionTransacted" set to "true": Transactional acknowledgment after successful listener execution; guaranteed redelivery in case of exception thrown.

+0

源文檔:[Spring Framework的AbstractMessageListenerContainer](http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jms/listener/AbstractMessageListenerContainer.html ) – 2017-05-26 09:23:08

-1

使用下面的代碼它會工作。

<bean id="{containerName}" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> 
    <property name="connectionFactory" ref={connectionFactoryBean} /> 
    <property name="destinationName" ref="{queue}" /> 
    <property name="messageListener" ref="{listner}" /> 
    <property name="sessionAcknowledgeModeName" value="CLIENT_ACKNOWLEDGE"/> 
</bean> 
-1

在消費者的消息中調用acknowledge()方法。

Consider the following scenario: An application receives but does not acknowledge a message. The application receives a subsequent message and acknowledges it. What happens to the former message? The former message is also considered acknowledged. Generally, acknowledging a particular message acknowledges all prior messages the session receives. In the above output, only message 5 is explicitly acknowledged. All the messages before message 5 are implicitly acknowledged. Messages after message 5 are not acknowledged.

欲瞭解更多詳情,請參閱this article

還要檢查本文Sun Java System Message Queue 4.3 Developer's Guide for Java Clients

3

如今春通過純JMS消息監聽器提供了良好的包裝。

請參閱JavaDocs AbstractMessageListenerContainer

"sessionAcknowledgeMode" set to "CLIENT_ACKNOWLEDGE" : Automatic message acknowledgment after successful listener execution; best-effort redelivery in case of a user exception thrown as well as in case of other listener execution interruptions (such as the JVM dying).

所以,當你定義一個@JmsListener方法,確認自動當它成功完成發送,但你可以拋出一個異常,再次收到消息。