当流包含不同类型的通道时,如何调用sendAndReceive?

时间:2014-08-25 16:58:23

标签: java spring integration spring-integration

我花了不少时间阅读有关Spring Integration的内容。今天我开始尝试框架。尽管我阅读了所有内容,但我仍然无法理解它的工作方式。我希望这里的人能让我回到正轨。

我定义了以下频道和端点:

<in:channel id="orderSource"/>
<in:service-activator input-channel="orderSource" 
                          ref="defaultOrderService"
                          method="placeOrder"/>

由于频道是DirectChannel,我希望一切都在一个线程中发生,并在最后得到一个返回值。

placeOrder方法如下所示:

@Override
public Order placeOrder(Order order) {
   return order;
}

在我的主要方法中,我有:

MessageChannel input = context.getBean("orderSource", MessageChannel.class);
Message<Order> message = MessageBuilder.withPayload(new Order(123)).build();
MessagingTemplate messenger = new MessagingTemplate(input);
Message<?> result = messenger.sendAndReceive(message);
Object found = result.getPayload();

这一切都像魅力一样。 found是服务激活器发回的顺序。

当我想通知一组订户已下订单时,我的问题就出现了。为简单起见,让我们同步这样做:

<in:channel id="orderSource"/>
<in:service-activator input-channel="orderSource"
                      output-channel="savedOrders"
                      ref="defaultOrderService"
                      method="validateOrder"/>

<in:publish-subscribe-channel id="savedOrders"/>

<in:outbound-channel-adapter channel="savedOrders"
                             ref="defaultOrderService"
                             method="notifyCustomerService"/>

<in:outbound-channel-adapter channel="savedOrders"
                             ref="defaultOrderService"
                             method="notifyShipmentManager"/>

<in:outbound-channel-adapter channel="savedOrders"
                             ref="defaultOrderService"
                             method="notifyWarehouseManager"/>

现在的问题是,当我调用sendAndReceive时,输入通道应该期待什么呢?

我当前的代码块,我从未到达主线程的末尾。

我如何确保收到包含服务激活器结果的回复,因为它已将其传递给所有订阅者?

此外,我非常好奇当流中存在异步通道时,给定通道在返回值方面可以期待什么。我希望在事务结束时和新线程生成之前得到结果,但我不知道该怎么做。

有任何想法,建议或指导吗?

2 个答案:

答案 0 :(得分:1)

据推测,您的“notify”方法返回null。如果是这种情况,则没有“回复”发送到MessagingTemplate

让最后一个返回订单,或者将<bridge/>作为第四个订阅者添加到pub-sub频道。

通往无处的桥梁只是一座没有输出通道的桥梁。当消息到达产生回复的端点,并且没有output-channel时,消息的replyChannel标头用于将回复路由到发起者。

它也适用于异步通道,但在我提供指导之前,我需要了解您的要求。

另外,请考虑在主叫方使用Messaging Gateway,而不是自己构建消息并使用MessagingTemplate。该框架不是将您的调用者暴露给消息传递基础结构,而是为您创建一个代理,它将负责所有这些并且您只需与POJI进行交互。

答案 1 :(得分:0)

我花了一些时间阅读,我发现这都是在消息或网关中配置回复通道,并使用桥接,就像Gary Rusell建议为我做的那样。

这是我的代码,正在运行:

<in:channel id="arrivals"/>
<in:service-activator input-channel="arrivals"
                      output-channel="validated"
                      ref="defaultOrderService"
                      method="validateOrder"/>
<in:channel id="validated"/>
<in:service-activator input-channel="validated"
                      output-channel="persisted"
                      ref="defaultOrderService"
                      method="placeOrder"/>

<in:publish-subscribe-channel id="persisted"/>

<in:channel id="replyChannel"/>

<in:bridge input-channel="persisted"  output-channel="replyChannel"/>

<in:outbound-channel-adapter channel="persisted"
                             ref="defaultOrderService"
                             method="notifyCustomerService"/>

<in:outbound-channel-adapter channel="persisted"
                             ref="defaultOrderService"
                             method="notifyShipmentManager"/>

<in:outbound-channel-adapter channel="persisted"
                             ref="defaultOrderService"
                             method="notifyWarehouseManager"/>

<in:gateway id="orderService"
            service-interface="codemasters.services.OrderService"
            default-request-channel="arrivals"
            default-reply-channel="replyChannel"/>

使用网关,现在看起来都很凉爽了:

OrderService service = context.getBean("orderService", OrderService.class);
Order result = service.validateOrder(new Order(4321));