简体   繁体   English

Apache 骆驼聚合路由异常

[英]Apache Camel aggregate route with exception

I want to use Apache Camel parallel multicast to 3 routes and aggregate (and wait for) 2 of them while leave 3rd go on its own (3rd one should not block first two).我想将 Apache Camel 并行多播用于 3 条路由并聚合(并等待)其中 2 条,同时单独留下第 3 条 go(第 3 条不应阻止前两条)。 I also need to process these two in "all" cases meaning that if one of them fails (eg throws an exception during processing), it should be aggregated as well.我还需要在“所有”情况下处理这两个,这意味着如果其中一个失败(例如,在处理过程中抛出异常),它也应该被聚合。

From what I understood from Camel documentation, that behavior should be "default" as long as you don't specify say stopOnException.根据我从 Camel 文档中了解到的情况,只要您不指定 stopOnException,该行为就应该是“默认的”。 But what happens is that exchange with exception never gets to my AggregationStrategy.但是发生的是异常交换永远不会进入我的聚合策略。 What is kind of weird is that processors behind aggregate get executed even when there is completionSize(2).有点奇怪的是,即使有 completionSize(2),聚合后面的处理器也会被执行。

So my question is: How is it possible that route after aggregation continues without processing exchange with the exception in AggregationStrategy?所以我的问题是:聚合后的路由怎么可能继续而不处理 AggregationStrategy 中的交换? And how to solve my case correctly?以及如何正确解决我的案子? Please note that doing.to("direct:sync") is not that case because this exception may be thrown from the route that is completely out of multicast-aggregate part of routes.请注意 doing.to("direct:sync") 不是这种情况,因为此异常可能会从完全超出路由的多播聚合部分的路由中抛出。

Here is the sample code (ExceptionThrowingProcessor throws MyException, PropertySetterProcessor is not important):下面是示例代码(ExceptionThrowingProcessor 抛出 MyException,PropertySetterProcessor 不重要):

CamelContext context = new DefaultCamelContext();
RouteBuilder builder = new RouteBuilder() {
    @Override
    public void configure() throws Exception {
    }
};

builder.onException(MyException.class)
        .process(new PropertySetterProcessor("a", "onException"))
        .handled(true);

builder.from("direct:input")
        .process(new PropertySetterProcessor("a", "before-multicast"))
        .multicast()
        .parallelProcessing()
        .shareUnitOfWork()
        .to("direct:part1", "direct:part2", "direct:part3")

builder.from("direct:part1")
        .process(new PropertySetterProcessor("a", "part1"))
        .to("direct:sync");

builder.from("direct:part2")
        .process(new PropertySetterProcessor("a", "part2"))
        .process(new ExceptionThrowingProcessor("oops")) // throws MyException
        .to("direct:sync");

builder.from("direct:part3")
        .process(new PropertySetterProcessor("a", "part3"));
// don't want this to be aggregated within direct:sync

builder.from("direct:sync")
        .aggregate(new TestAggregationStrategy())
        // strategy.aggregate is called only once (from part1) but not from part2 :(
        .constant(true)
        .completionSize(2)
        .process(new PropertySetterProcessor("a", "after-aggregation"));

context.addRoutes(builder);
context.start();

ProducerTemplate template = context.createProducerTemplate();
template.send("direct:input", new DefaultExchange(context, ExchangePattern.InOut));

I have a possible solution:我有一个可能的解决方案:

  1. continued(true) at the end of your onException()onException()结束时continued(true)
  2. in the processor of exception, add some prop into exchange, like skipNextStep = true .在异常处理器中,添加一些 prop 到 exchange 中,比如skipNextStep = true
  3. At the end of exception handler, add your desired body for aggregation在异常处理程序的末尾,添加您想要的聚合体
  4. Surround the rest of your route with .choice().when(simple("${exchangeProperty.skipNextStep == null}")) and .end() , so that if it's not set, means previous step work, process;.choice().when(simple("${exchangeProperty.skipNextStep == null}")).end()包围你的路线的 rest ,这样如果它没有设置,意味着前面的步骤工作,处理; if not, do nothing and return same exchange.如果不是,则什么都不做并返回相同的交换。 So you can skip rest of the split route and go to aggregation directly.所以可以跳过split路由的rest和go直接聚合。

Not a perfect solution but a workaround.不是完美的解决方案,而是解决方法。

I think split part can add a keyword like when().skipRestAndAggregate() so that it skips rest of the route and shortcircuit.我认为拆分部分可以添加when().skipRestAndAggregate()之类的关键字,以便它跳过路由和短路的 rest。

Replace handled(true) with continue(true) on onException block. 在onException块上用continue(true)替换处理(true)。 Refer this for more info http://camel.apache.org/exception-clause.html 有关详细信息,请参阅此http://camel.apache.org/exception-clause.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM