I asked this question on stack overflow but didn't get a response so asking
here
https://stackoverflow.com/questions/78720143/camel-notifybuilder-does-not-match-when-exception-is-thrown

It seems that camel's NotifyBuilder
<https://camel.apache.org/manual/notify-builder.html> works in normal
message processing but does not work when exceptions are thrown.

Please see the following test case where I create the following routes

   - direct:route-a adds "a" to a list and passes to direct:route-b
   - direct:route-b adds "b" to a list and throws exception
   - errorHandler routes to direct:dead-letter as a deadLetterChannel
   - direct:dead-letter adds "dead" to a list

I can see that the list contains "a", "b", "dead" when I send a message to
direct:route-a

But the NotifyBuilders for direct:route-b and direct:dead-letter don't
match for some reason.

Is there a bug in NotifyBuilder where they don't match when exceptions are
thrown? Am I using NotifyBuilder incorrectly? I've tried both
NotifyBuilder.whenDone(1) and NotifyBuilder.whenFailed(1) and neither
causes a match.

Looking at the NotifyBuilder javadoc
<https://www.javadoc.io/doc/org.apache.camel/camel-core/2.25.4/org/apache/camel/builder/NotifyBuilder.html#whenDone-int->
I
see the following comment for whenDone(...)

> The difference between done and completed is that done can also include
failed messages, where as completed is only successful processed messages.

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;
@Slf4jpublic 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();
    }
}

Reply via email to