从组合路线中获得准确的响应

时间:2015-05-17 20:42:01

标签: java apache-camel

我有一个动态路由创建者Web应用程序。根据流程设计,我制作了一条骆驼路线。路由可能包含多播,过滤器,聚合,处理器等。在通过UI设计流程后,我的路由已经创建如下:

from("seda:start").routeId("idx")
    .multicast()
      .to("direct:a", "direct:b", "direct:c")
      .parallelProcessing()
    .end();

from("direct:a").transform(constant("A")).delay(1000).to("direct:merge");
from("direct:b").transform(constant("B")).delay(2000).to("direct:merge");
from("direct:c").transform(constant("C")).delay(3000).to("direct:merge");

from("direct:merge")
    .aggregate(new MyAggregationStrategy()).constant(true).completionSize(3)
    .to("mock:end");

我有一个API可以将此路由的结果提供给用户。当我使用InOut MEP执行此路由时,响应是' C'但是模仿:结束对ABC':

感到满意
MockEndpoint mock = getMockEndpoint("mock:end");
    mock.expectedBodiesReceived("ABC");  //works as expected

    String reply = template.requestBody("seda:start", "", String.class);

    assertEquals("ABC", reply);   //it returns 'C', but I expect 'ABC'

    assertMockEndpointsSatisfied();

如何通过同步调用更改代码以获得汇总结果?这是代码:

public class ResponseTest extends CamelTestSupport {

@Test
public void testAsyncInOut() throws Exception {
    MockEndpoint mock = getMockEndpoint("mock:end");
    mock.expectedBodiesReceived("ABC");  //works as expected

    String reply = template.requestBody("seda:start", "", String.class);

    assertEquals("ABC", reply);   //it returns 'C', but I expect 'ABC'

    assertMockEndpointsSatisfied();
}

@Override
protected RouteBuilder createRouteBuilder() throws Exception {
    return new RouteBuilder() {
        @Override
        public void configure() throws Exception {
            from("seda:start").routeId("idx")
                .multicast()
                    .to("direct:a", "direct:b", "direct:c")
                    .parallelProcessing()
                .end();

            from("direct:a").transform(constant("A")).delay(1000).to("direct:merge");
            from("direct:b").transform(constant("B")).delay(2000).to("direct:merge");
            from("direct:c").transform(constant("C")).delay(3000).to("direct:merge");

            from("direct:merge")
                .aggregate(new MyAggregationStrategy()).constant(true).completionSize(3)
                .to("mock:end");
        }
    };
}

class MyAggregationStrategy implements AggregationStrategy {

    public Exchange aggregate(Exchange oldExchange, Exchange newExchange) {
        if (oldExchange == null) {
            // this is the first time so no existing aggregated exchange
            return newExchange;
        }

        // append the new word to the existing
        String body = newExchange.getIn().getBody(String.class);
        String existing = oldExchange.getIn().getBody(String.class);

        oldExchange.getIn().setBody(existing + body);
        return oldExchange;
    }
}
}

修改

将消息多播到5个不同的端点并不意味着以后会聚合所有消息。所以我不能在组播定义中使用聚合策略。其中一些可能用于另一种工作。流定义可能是这样的: 多播消息到''''''''' e'终点,' a'和' b'可以汇总在一起('直接:merge1'),' c'并且' d'汇总在一起('直接:merge2')和' e'可以用于另一件事。 最终聚合器将汇总直接:merge1'和'直接:merge2' 到'直接:merge3'。所有这些端点都是动态创建的('直接:','直接:b','直接:c','直接:d' '直接:E','直接:merge1','直接:merge2','直接:merge3&#39)。将按以下方式创建此方案:

from("seda:start").routeId("idx")
    .multicast()
        .to("direct:a", "direct:b", "direct:c", "direct:d", "direct:e")
        .parallelProcessing()
    .end();

from("direct:a").transform(constant("A")).delay(1000).to("direct:merge1");
from("direct:b").transform(constant("B")).delay(2000).to("direct:merge1");

from("direct:c").transform(constant("C")).delay(3000).to("direct:merge2");
from("direct:d").transform(constant("D")).delay(1000).to("direct:merge2");

from("direct:e").transform(constant("E")).delay(1000).to("mock:anywhere");

from("direct:merge1").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("direct:merge3");
from("direct:merge2").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("direct:merge3");

from("direct:merge3").aggregate(new MyAggregationStrategy()).constant(true).completionSize(2).to("mock:end");

当我向seda发送消息时:开始,我希望ABDC,但我得到了E'。有没有办法获得最终的汇总信息(' ABDC')?这是测试方法:

@Test
public void testAsyncInOut() throws Exception {
    MockEndpoint mock = getMockEndpoint("mock:end");
    mock.expectedBodiesReceived("ABDC");  //works as expected

    String reply = template.requestBody("seda:start", "", String.class);

    assertEquals("ABDC", reply);   //it returns 'E' because of default multicast behavior, but I expect 'ABDC'

    assertMockEndpointsSatisfied();
}

1 个答案:

答案 0 :(得分:1)

来自multicast documentation

  

默认情况下,Camel会将最后一个回复用作传出消息。

如果要将多播的结果聚合到单个消息中,请在多播定义中说明。

@Override
public void configure() throws Exception {
  from("seda:start").routeId("idx")
    .multicast(new MyAggregationStrategy()) //Put the Aggregation Strategy here!
      .to("direct:a", "direct:b", "direct:c")
      .parallelProcessing()
    .end();

  from("direct:a").transform(constant("A")).delay(1000).to("direct:merge");                      
  from("direct:b").transform(constant("B")).delay(2000).to("direct:merge");
  from("direct:c").transform(constant("C")).delay(3000).to("direct:merge");

  from("direct:merge")
    .to("mock:end");
}

请注意,您的模拟端点现在将被调用3次,因为聚合直到稍后才会发生。您需要相应地修改测试。

相关问题