2017-07-17 103 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()'偷看到队列中,而不检索 –