JMS 入站网关 - 回复目标队列发送不可能时的错误处理

JMS Inbound Gateway - error handling when reply destination queue send is not possible

我们有一个 EIP 流,它使用基于注释的 spring:4.2.x API、spring-integration:4.2.x API 和 spring-integration-java-dsl:1.1.0 API 从 Websphere MQ 队列接收消息,进行一些处理,最后 return 对另一个 Websphere MQ 队列的响应。对于此流程,我们使用 JMS Inbound Gateway 从一个队列同步接收消息,处理它们并将响应发送回另一个队列。

JMS Inbound Gateway 配置了 errorChannel 以便 RuntimeException 被路由到它(这工作正常)。但是在测试期间,当我们故意在流的响应 Websphere MQ 队列上应用 PUT_INHIBIT(即导致流无法将响应发送回回复队列)时,spring 日志显示以下内容WARNING 日志消息:

WARN ... - Execution of JMS message listener failed, and no ErrorHandler has been set. javax.jms.JMSException: MQJMS2007: failed to send message to MQ queue.

我们知道我们可以通过在 MLC 本身上配置 ErrorHandler 来删除 WARNING 日志,但是,这给我们带来问题的原因是当我们将响应路由回去时,我们实际上使用 .routeToRecipients() 调用路由 .setIgnoreFailures(false) 和两个收件人 - 第一个收件人路由到 JMS Inbound GatewayreplyChannel,第二个路由到 post-send 流程,以便我们可以进行数据库更新等。这里的想法是,如果第一个接收者发送失败(即当响应队列不可用时),post-send 流程不会执行但是而是执行错误处理流程(例如 errorChannel 流程)。但是在描述的错误场景中,我们看到了警告日志,并且流程的 post-send 流程仍然执行而不是 errorChannel 的流程...

就好像在这一点上,JMS Inbound GatewayerrorChannel 不再适用。这个对吗?这是预期的行为吗?如果是,这是否意味着我们应该使用 Inbound/Outbound Adapter 而不是 Inbound Gateway 来响应 post-发送意图?

JMS MLC 配置:

@Bean( destroyMethod = "shutdown")
public DefaultMessageListenerContainer serviceMLC() throws Exception {

    DefaultMessageListenerContainer mlc = new DefaultMessageListenerContainer();
    mlc.setAutoStartup(false);
    mlc.setConnectionFactory(serviceCCF);
    mlc.setDestination(requestMqQueue);
    mlc.setAcceptMessagesWhileStopping(false);
    return mlc;
}

JMS 入站网关配置:

@Bean
public IntegrationFlow serviceFlow() {

    return IntegrationFlows
            .from(Jms
                    .inboundGateway(serviceMLC)
                    .autoStartup(true)
                    .defaultReplyDestination(responseMqQueue)
                    .replyChannel(responseOutCh)
                    .replyTimeout(180000)
                    .correlationKey("JMSCorrelationID")
                    .errorChannel(serviceErrorCh)
                    )
            .channel(serviceInCh)
            .get();
}

是;网关不能那样工作。

当您将回复发送到网关时,它会在网关中排队,直到线程 returns 到达网关;届时,将接收并发送回复。因此,直到稍后(在调用第二个收件人流之后)才会发生发送失败。

是的,要执行您想要的操作,您应该改用通道适配器,因为失败将 运行 直接发生在调用线程上。