2013-04-18 113 views
1

我想從Java中的MQ隊列中讀取消息,並且在處理異常時需要回滾時我有點困惑。MQ消息回滾

我有一個閱讀器類,在循環中運行並查找消息。當我初始化閱讀器時,它會創建一個連接和一個會話。然後,當要在循環中讀取消息時,它會創建一個MQQueueMQQueueReceiver。這工作正常,我得到一個JMSMessage隊列,然後交給另一個線程工作。如果工作線程失敗,我想將該消息放回到隊列中(這樣它會被羣集中的其他節點重試)。

我的問題是,我該如何回滾?我注意到在MQQueueSession類中有一個rollback()方法。但我正在重複使用同一個會話來處理所有消息。我是否明白應該爲每條消息創建一個新的會話,而不是一遍又一遍地重複使用同一個消息?

這對我來說很直觀。

此外,會話使用connection.createQueueSession(false, Session.CLIENT_ACKNOWLEDGE);創建。我是否應該使用另一個標誌,而不是CLIENT_ACKNOWLEDGE

回答

1

您應該使用Session.SESSION_TRANSACTED標誌和Session.commit/Sessiuon.rollback提交/回滾在當前事務中進行

+0

完美。謝謝 – mprivat

1

注意所有消息的JMS 1.1規範會話定義爲:

會議 - 在規格上發送和接收消息

後來一個單線程上下文,它說:

限制對會話的併發訪問有兩個原因。首先,會話是支持事務的JMS實體。很難實現多線程的事務,這是 。其次,會話支持異步消息消費。重要的是,JMS不要求用於異步消息的客戶端代碼能夠處理多個併發的消息。另外,如果一個會話已經建立了多個異步使用者,重要的是客戶端並不是強制 來處理這些單獨使用者同時執行的情況。這些限制使JMS更易於用於典型的 客戶端。更復雜的客戶可以通過使用多個會話來獲得他們想要的併發性。

所以,不,你不需要每個消息一個會話。但是,即使您已將這些消息交給其他線程,並且此行爲符合規範,在會話期間生成或使用的所有消息也會被提交或回滾到一起,即

使用Evgeniy描述的事務會話和COMMIT/ROLLBACK,但也要注意保持同一會話範圍內的消息都在同一工作單元內。