Spring integration Spring集成捕获JMSTemplate生存时间超时

Spring integration Spring集成捕获JMSTemplate生存时间超时,spring-integration,ibm-mq,spring-jms,Spring Integration,Ibm Mq,Spring Jms,我有发送到IBM MQ队列的JMS消息,如果远程客户端(我无法控制远程客户端)在给定时间(比如1分钟)内没有使用该消息,则该消息应该过期(我让过期部分工作,在JMSTemplate上使用setExplicitQosEnabled和setTimeToLive“MQ删除消息”)并且应该通知消息发送者(我的SI代码),消息没有传递到远程客户端,以便将过期的消息重新路由到另一个队列 我不知道如何使用Spring集成来实现这个模式,尤其是当消息是异步发送的,并且只在返回时关联(MessageID->Cor

我有发送到IBM MQ队列的JMS消息,如果远程客户端(我无法控制远程客户端)在给定时间(比如1分钟)内没有使用该消息,则该消息应该过期(我让过期部分工作,在JMSTemplate上使用setExplicitQosEnabled和setTimeToLive“MQ删除消息”)并且应该通知消息发送者(我的SI代码),消息没有传递到远程客户端,以便将过期的消息重新路由到另一个队列

我不知道如何使用Spring集成来实现这个模式,尤其是当消息是异步发送的,并且只在返回时关联(MessageID->CorrelationID)

我想我可以有某种形式的:

1) ErrorMessageExceptionTypeRouter,但我需要有效负载,以便可以重新发送消息,但我不确定如何实现这一点(如何在超时时从MQ回调到JMSTemplate或路由到另一个队列,并有一个辅助路由侦听该队列并重新路由)

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

非常感谢您对如何最好地实施上述内容的任何帮助

进度报告: 我尝试使用方法
JMSTemplate.receiveSelected(destination,messageSelector)查询MQ这是Artem Bilan建议的。计划是手动查找客户端在给定时间内未使用的消息。(提供商必须跟踪所有消息,并在计时器过期后尝试使用其messageID检索每条消息,而不是使用TimeToLive message Expire)此解决方案将跟踪和计时发送的每条消息并尝试检索每条消息的责任交给提供商(大多数消息不可用)使其效率低下,但却是可行的解决方案。不幸的是,当我调用时,IBM MQ不喜欢它:
JMSTemplate.receiveSelected(destination,messageSelector)我得到以下错误:

org.springframework.jms.InvalidSelectorException:JMSWMQ2008:无法打开MQ队列'MY.TEST.IN'。;嵌套异常为com.ibm.msg.client.jms.DetailedInvalidSelectorException:JMSWMQ2008:未能打开MQ队列“MY.TEST.IN”。
JMS试图执行MQOPEN,但WebSphere MQ报告了一个错误。
使用链接异常确定此错误的原因。检查指定的队列和队列管理器是否定义正确。;嵌套异常为com.ibm.mq.MQException:JMSCMQ0001:WebSphere mq调用失败,代码为“2”(“MQCC_失败”)原因为“2459”(“MQRC_选择器语法错误”)。


但是使用
JMSTemplate.receive(目的地)会从队列中读取消息

您的解释对于DLQ场景来说已经足够了:

您需要的是为原始队列配置DLQ,过期后消息将移动到DLQ


您确实可以将应用程序中的侦听器配置到此DLQ,并通过Spring集成执行适当的逻辑:

以下代码导致IBM MQ V8自动将过期消息重新路由到JMSReplyTo队列(感谢JoshMc在上面的评论中提出的建议)

我在这里找到的JMS_IBM_Report_过期值为14680064:


我需要找到这个JAR并将其添加到我的项目中,但是MQ会删除过期的消息并将其存放在我指定的回复队列中

在IBM MQ中,过期消息不会发送到DLQ,它们“过期”或者不再出现在队列中。DLQ可以很好地处理根本没有传递的消息,但在我的场景中,消息是传递的,但没有在要求的时间范围内读取。我想知道我是否可以从JMS会话中检索过期的消息?可能发送的消息在交付和读取后具有某种状态,而不是交付和过期?如果消息是从队列中读取的,它也会从队列中消失。您可以尝试使用
JmsTemplate.browse()
来窥视队列,而不必检索hi-Artem,不幸的是,这意味着我需要一个监视者来不断监视队列,并且需要跟踪进入队列的所有消息,以确定哪些消息仍然存在。当前,当消息过期时,MQ将删除该消息,因此无法浏览该消息。头奖是在邮件未送达时收到回电,但如何回电?我正在使用的另一个选项是JMSXDeliveryCount,当消息被读取(在接收实例上)时,它从零变为1,但是发送方持有的引用并没有增加。好吧,这不好说,但看起来IBM MQ不适合您的用例。很抱歉,我忘了提到,对于浏览方法,您不应该自己使用expire并实现删除逻辑,不再依赖MQ。我不知道如何回答特定于Spring的配置,但是在IBM MQ中,您可以对发送的原始消息设置报告选项,这将导致目标队列管理器在原始消息过期时发回报告消息,您可以将其标记为也包含原始消息。嗨,Josh,这些报告选项,这是我可以在JMS消息本身上设置的吗(可能在标题中?)或是否需要在队列管理器上执行(不幸的是,这是由另一个部门负责的,因此不太容易更改!)以及如何将报告返回到我的应用程序?(可能通过JMS会话?)这在IBM MQ v8 KC页面中有记录“”。您可以将
JMS\u IBM\u Report\u Expiration
属性设置为
MQRO\u Expiration\u WITH\u FULL\u DATA
。接收队列管理器将发回报告消息,其中
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;
});