2017-07-17 73 views
4

如果遠程客戶端(我無法控制遠程客戶端)在給定時間內沒有使用消息,那麼我有發送到IBM MQ Queue的JMS消息(Say 1分鐘)消息應該過期(我有Expire部分工作,「MQ在JMSTemplate上使用setExplicitQosEnabled和setTimeToLive刪除消息」),並且應該通知消息發送者(我的SI代碼)消息沒有傳遞給遠程客戶端,以便過期的消息可以重新路由到另一個隊列。Spring集成捕獲JMSTemplate生存時間超時

我不確定如何使用Spring Integration實現此模式,特別是因爲消息是異步發送的,並且僅在返回時才相關(MessageID - > CorrelationID)。

我想我可能有某種形式的:

1)ErrorMessageExceptionTypeRouter,但我需要的有效載荷,所以我可以重新發送該消息,我不知道如何實現這個(如何從MQ回調到JmsTemplate的或路由到另一個隊列超時,並有一個第二路由監聽該隊列和重新路由)

2)WireTap,但我認爲這將意味着阻止發送方(請求/響應模型) msg將被遠程客戶端刪除。我再次不確定如何實現這一點。

任何有關如何最好地實施以上的幫助非常感謝。

進度報告: 我曾嘗試利用該方法JMSTemplate.receiveSelected(destination, messageSelector);是阿爾喬姆比蘭建議查詢MQ。該計劃是在給定時間內手動查找客戶尚未使用的消息。 (提供者必須跟蹤所有消息,並在計時器過期時嘗試使用其messageID檢索每條消息,而不是使用TimeToLive消息到期)此解決方案將提供者的責任追蹤並定時發送每條消息並嘗試檢索每條消息(大多數應該不可用)使其效率低下,但是可行的解決方案。不幸的是IBM MQ不喜歡它,當我打電話:JMSTemplate.receiveSelected(destination, messageSelector);我得到以下錯誤:

org.springframework.jms.InvalidSelectorException: JMSWMQ2008: Failed to open MQ queue ‘MY.TEST.IN'.; nested exception is com.ibm.msg.client.jms.DetailedInvalidSelectorException: JMSWMQ2008: Failed to open MQ queue 'MY.TEST.IN'. JMS attempted to perform an MQOPEN, but WebSphere MQ reported an error. Use the linked exception to determine the cause of this error. Check that the specified queue and queue manager are defined correctly.; nested exception is com.ibm.mq.MQException: JMSCMQ0001: WebSphere MQ call failed with compcode '2' ('MQCC_FAILED') reason '2459' ('MQRC_SELECTOR_SYNTAX_ERROR').

但是使用JMSTemplate.receive(destination);具有相同目標並讀出隊列中的消息。

+0

我不確定如何回答Spring的特定配置,但在IBM MQ中,您可以在您發送的原始郵件上設置報告選項,這將導致目標隊列管理器在原始郵件過期時發回報告郵件,您可以將其標記爲包括原始消息。 – JoshMc

+0

嗨Josh,這些報告選項,這是我可以在JMS消息本身上設置的東西(在標題中可能?),還是需要在隊列管理器上完成(不幸的是,這是由另一個部門照顧,所以不那麼容易改變了!)以及這些報告如何返回到我的應用程序? (通過JMS會話可能嗎?) – MarcA

+1

這在IBM MQ v8 KC頁面「[JMS報告消息]」(https://www.ibm.com/support/knowledgecenter/en/SSAW57_8.0.0/com.ibm。 websphere.nd.doc /信息/ AE/AE/rmj_reports.html)」。您可以將'JMS_IBM_Report_Expiration'屬性設置爲'MQRO_EXPIRATION_WITH_FULL_DATA'。當消息過期到MQMD中指定的ReplyToQueue和ReplyToQmgr時,接收隊列管理器將發回包含原始消息內容的報告消息。 – JoshMc

回答

3

下面的代碼將導致IBM MQ V8到automagicaly重新路由過期消息的JMSReplyTo隊列,(由於JoshMc爲他的上述意見建議)

jmsTemplate.setTimeToLive(3000l); 
jmsTemplate.setExplicitQosEnabled(true); 
jmsTemplate.setSessionAcknowledgeMode(Session.AUTO_ACKNOWLEDGE); 
jmsTemplate.setDeliveryMode(DeliveryMode.PERSISTENT); 
jmsTemplate.setPriority(Message.DEFAULT_PRIORITY); 
jmsTemplate.send(destinationName, session -> { 
    TextMessage toSend = session.createTextMessage(message) 
    toSend.setIntProperty("JMS_IBM_Report_Expiration", 14680064); 
    Queue queue = session.createQueue(「TEST.EXPIRE.REPORT」); 
    toSend.setJMSReplyTo(queue); 

    return toSend; 
}); 

的14680064的JMS_IBM_Report_Expiration值我發現這裏:https://www.ibm.com/support/knowledgecenter/en/SS7K4U_8.0.0/com.ibm.websphere.javadoc.doc/web/apidocs/constant-values.html#com.ibm.websphere.sib.api.jms.ApiJmsConstants.MQRO_EXPIRATION_WITH_FULL_DATA

我需要找到這個JAR並將其添加到我的項目中,但MQ刪除過期的消息並將其存儲在指定的隊列中。

0

您對DLQ方案的解釋完全足夠:https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_8.0.0/com.ibm.mq.adm.doc/q020730_.htm

您需要的是爲您的原始隊列配置DLQ,到期後郵件將移至DLQ。

你真的可以在應用程序中創建監聽這個DLQ並通過Spring集成已經執行適當的邏輯:http://docs.spring.io/spring-integration/reference/html/jms.html#jms-message-driven-channel-adapter

+0

不會轉到DLQ,它們「過期」並且不再出現在隊列中。 – JoshMc

+0

嗨阿爾喬姆,不幸的是,喬希指出,消息就消失了。 DLQ適用於根本沒有發送的消息,但在我的情況下,消息已發送但未在規定的時間範圍內讀取。我想知道是否可以從JMS會話中檢索過期的消息?可能發送的消息在發送和讀取vs發送和過期之後具有某種狀態? – MarcA

+0

如果從隊列中讀取消息,它也會從隊列中消失。您可以嘗試使用'JmsTemplate.browse()'偷看到隊列中,而不檢索 –