使用 Spring 集成和 Jms 将 Soap 消息放入队列的 Web 服务

Web service putting Soap message in queue with Spring Integration and Jms

我想使用 Spring 集成来公开一个简单的 Web 服务,该服务将传入消息推送到 ActiveMQ 并立即响应。我的首选解决方案是使用 IntegrationFlow 连接到 Jms.outboundAdapter 的 MarshallingWebServiceInboundGateway。在 Gateway 和 IntegrationFlow 片段下方。问题是适配器不提供网关期望的响应 (duh)。我从服务返回的响应是空的 202,延迟大约 1500 毫秒。这是由我在 TRACE 日志中看到的回复超时引起的:

"2020-04-14 17:17:50.101 TRACE 26524 --- [nio-8080-exec-6] o.s.integration.core.MessagingTemplate   : Failed to receive message from channel 'org.springframework.messaging.core.GenericMessagingTemplate$TemporaryReplyChannel@518ffd27' within timeout: 1000" 

任何地方都没有硬异常。另一个问题是我无法自己生成响应。在带适配器的 .handle 之后,我无法向 IntegrationFlow 添加任何内容。

  1. 还有其他方法可以尝试实现该场景吗?
  2. 如果可能的话,在没有更好方法的情况下,我如何生成和return响应?

很可能正确的方法是在两端都使用网关,但这是不可能的。我等不及响应,直到队列中的消息被消耗和处理。

'''

@Bean
public MarshallingWebServiceInboundGateway greetingWebServiceInboundGateway() {
    MarshallingWebServiceInboundGateway inboundGateway = new MarshallingWebServiceInboundGateway(
            jaxb2Marshaller()
    );
    inboundGateway.setRequestChannelName("greetingAsync.input");
    inboundGateway.setLoggingEnabled(true);
    return inboundGateway;
}

@Bean
public IntegrationFlow greetingAsync() {
    return f -> f
            .log(LoggingHandler.Level.INFO)
            .handle(Jms.outboundAdapter(this.jmsConnectionFactory)
                    .configureJmsTemplate(c -> {
                        c.jmsMessageConverter(new MarshallingMessageConverter(jaxb2Marshaller()));
                    })
                    .destination(JmsConfig.HELLO_WORLD_QUEUE));

}

'''

逻辑和假设完全正确:你不能在 one-way handle() 之后 return 并且类似于 Jms.outboundAdapter().

但是你的问题是你完全错过了 Spring 整合中的 first-class 公民之一 - MessageChannel。重要的是要理解,即使在像您这样的流程中,端点之间也存在通道(DSL 方法)-隐式(DirectChannel),就像您的情况一样,或者显式:当您在两者之间使用 channel() 时并可以在那里放置任何可能的实现:https://docs.spring.io/spring-integration/docs/5.3.0.M4/reference/html/dsl.html#java-dsl-channels

其中一个关键的通道实现是 PublishSubscribeChannel(JMS 规范中的 topic),当您可以将相同的消息发送到多个订阅端点时:https://docs.spring.io/spring-integration/docs/5.3.0.M4/reference/html/core.html#channel-implementations-publishsubscribechannel

在您的情况下,第一个订阅者应该是您现有的 one-way Jms.outboundAdapter()。还有一些东西会生成响应并将其回复为 replyChannel header.

为此 Java DSL 通过 sub-flows 配置提供了一个很好的钩子:https://docs.spring.io/spring-integration/docs/5.3.0.M4/reference/html/dsl.html#java-dsl-subflows

所以,publish-subscriber 的一些示例可能是这样的:

.publishSubscribeChannel(c -> c
                        .subscribe(sf -> sf
                                  .handle(Jms.outboundAdapter(this.jmsConnectionFactory))))
.handle([PRODUCE_RESPONSE])