Spring集成捕获JMSTemplate时间实时超时

时间:2017-07-17 13:53:09

标签: spring-integration ibm-mq spring-jms

我有发送到IBM MQ队列的JMS消息,如果远程客户端(我没有控制远程客户端)在给定时间内没有消耗该消息(说1分钟)消息应该过期(I让Expire部分工作," MQ使用JMSTemplate上的setExplicitQosEnabled和setTimeToLive删除消息"并且应该通知消息发送者(My SI Code)消息未被传递到远程客户端,以便过期的消息可以重新路由到另一个队列。

我不确定如何使用Spring Integration实现此模式,尤其是因为消息是异步发送的,并且仅在返回时关联(MessageID - > CorrelationID)。

我以为我可以有某种形式:

1)ErrorMessageExceptionTypeRouter,但我需要有效负载,所以我可以重新发送消息,我不知道如何实现这个(如何从MQ回调到JMSTemplate或路由到另一个队列的超时,并有一个辅助路由听取队列并重新路由)

2)WireTap,但我认为这意味着使用定时器阻止发送方(请求/响应模型)上的线程,该定时器监视远程客户端要删除的消息。我再次不确定如何实现这一点。

任何有关如何最好地实施上述内容的帮助都非常感谢。

进度报告 我尝试使用Artem Bilan建议的方法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);会从队列中读取消息。

2 个答案:

答案 0 :(得分:3)

以下代码导致IBM MQ V8自动将过期消息重新路由到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;
});

我在这里找到的JMS_IBM_Report_Expiration值14680064: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删除过期的消息并将其存放在我指定的队列回复中。

答案 1 :(得分:0)

您解释的内容完全足以支持DLQ方案:https://www.ibm.com/support/knowledgecenter/en/SSFKSJ_8.0.0/com.ibm.mq.adm.doc/q020730_.htm

您需要为原始队列配置DLQ,并在到期后将消息移至DLQ。

您真的可以在应用程序中为此DLQ配置一个侦听器,并通过Spring Integration执行适当的逻辑:http://docs.spring.io/spring-integration/reference/html/jms.html#jms-message-driven-channel-adapter