Camel NotifyBuilder 抛出异常时不匹配

问题描述 投票:0回答:1

看来camel的NotifyBuilder在正常消息处理中可以工作,但在抛出异常时不起作用。

请参阅以下测试用例,其中我创建了以下路线

  • direct:route-a
    将“a”添加到列表中并传递给
    direct:route-b
  • direct:route-b
    将“b”添加到列表中并引发异常
  • errorHandler
    路由至
    direct:dead-letter
    作为
    deadLetterChannel
  • direct:dead-letter
    将“死亡”添加到列表中

当我向

direct:route-a

发送消息时,我可以看到列表包含“a”,“b”,“dead”

但是

NotifyBuilder
direct:route-b
direct:dead-letter
由于某种原因不匹配。

NotifyBuilder
是否存在抛出异常时它们不匹配的错误?我是否错误地使用了
NotifyBuilder
?我已经尝试了
NotifyBuilder.whenDone(1)
NotifyBuilder.whenFailed(1)
,但都没有导致匹配。

查看 NotifyBuilder javadoc 我看到以下评论

whenDone(...)

done 和completed 之间的区别在于done 还可以包含失败的消息,而completed 则仅是成功处理的消息。

import lombok.extern.slf4j.Slf4j;
import org.apache.camel.CamelContext;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.builder.NotifyBuilder;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.impl.DefaultCamelContext;
import org.apache.camel.impl.engine.DefaultProducerTemplate;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import static org.assertj.core.api.Assertions.assertThat;

@Slf4j
public class NotifyBuilderTest {
    private CamelContext camelContext;
    private ProducerTemplate producerTemplate;
    private List<String> list;

    @BeforeEach
    public void beforeEach() throws Exception {
        list = new LinkedList<>();
        camelContext = new DefaultCamelContext();

        camelContext.addRoutes(new RouteBuilder() {
            @Override
            public void configure() {
                from("direct:route-a")
                        .process(exchange -> list.add("a"))
                        .to("direct:route-b");

                from("direct:route-b")
                        .process(exchange -> list.add("b"))
                        .process(exchange -> { throw new Exception("foo"); });

                errorHandler(deadLetterChannel("direct:dead-letter"));

                from("direct:dead-letter")
                        .process(exchange -> list.add("dead"));
            }
        });
        producerTemplate = new DefaultProducerTemplate(camelContext);

        camelContext.start();
        producerTemplate.start();
    }

    @AfterEach
    public void afterEach() {
        producerTemplate.stop();
        camelContext.stop();
    }

    @Test
    public void testNotify() {
        NotifyBuilder notifierA = new NotifyBuilder(camelContext)
                .from("direct:route-a")
                .whenDone(1)
                .create();
        NotifyBuilder notifierB = new NotifyBuilder(camelContext)
                .from("direct:route-b")
                .whenDone(1)
                .create();
        NotifyBuilder notifierDead = new NotifyBuilder(camelContext)
                .from("direct:dead-letter")
                .whenDone(1)
                .create();

        producerTemplate.sendBody("direct:route-a", null);

        // this succeeds
        assertThat(list).containsExactly("a", "b", "dead");

        // this succeeds
        assertThat(notifierA.matches(5, TimeUnit.SECONDS)).isTrue();

        // this fails
        assertThat(notifierB.matches(5, TimeUnit.SECONDS)).isTrue();

        // this fails
        assertThat(notifierDead.matches(5, TimeUnit.SECONDS)).isTrue();
    }
}
java exception testing apache-camel
1个回答
0
投票

事实证明,

NotifyBuilder.from(...)
仅匹配管道的入口点(在我的例子中为
direct:route-a
)。我能够通过使用
NotifyBuilder.from(...)
来匹配
route-a
NotifyBuilder.wereSentTo(...)
来匹配后续路线来解决我的问题。

我重构了测试用例如下

@Test
public void testNotify() {
  NotifyBuilder notifierA = new NotifyBuilder(camelContext)
      .from("direct:route-a")
      .whenDone(1)
      .create();
  NotifyBuilder notifierB = new NotifyBuilder(camelContext)
      .wereSentTo("direct:route-b")
      .whenDone(1)
      .create();
  NotifyBuilder notifierDead = new NotifyBuilder(camelContext)
      .wereSentTo("direct:dead-letter")
      .whenDone(1)
      .create();

  producerTemplate.sendBody("direct:route-a", null);

  assertThat(list).containsExactly("a", "b", "dead");
  assertThat(notifierA.matches(5, TimeUnit.SECONDS)).isTrue();
  assertThat(notifierB.matches(5, TimeUnit.SECONDS)).isTrue();
  assertThat(notifierDead.matches(5, TimeUnit.SECONDS)).isTrue();
}
© www.soinside.com 2019 - 2024. All rights reserved.