jaks
jaks

Reputation: 4587

Camel Java DSL Route with Choice proceeds only for last condition

I have choice with many options, but the route works only for last condition. For other conditions, the route is stuck and wont proceed further.

public class CamelChoiceTest {

  private CamelContext context;

  @Before
  public void initializeContext() throws Exception {

    RouteBuilder builder = new RouteBuilder() {
      public void configure() {

        from("direct:test")
          .choice()
            .when(header("number").isEqualTo("one")).to("direct:one")
            .when(header("number").isEqualTo("two")).to("direct:two")
            .when(header("number").isEqualTo("three")).to("direct:three")
          .endChoice()
          .log("only final condition reaches here");

        from("direct:one").log("one is selected");
        from("direct:two").log("two is selected");
        from("direct:three").log("three is selected");
      }
    };

    context = new DefaultCamelContext();
    context.addRoutes(builder);
    context.setTracing(true);
    context.start();
  }

  private void send(String header){
    Exchange exchange = new DefaultExchange(context);
    exchange.getIn().setHeader("number", header);
    exchange.getIn().setBody("test", String.class);
    ProducerTemplate producerTemplate = context.createProducerTemplate();
    // Send the request
    producerTemplate.send("direct:test", exchange);
  }

  @Test
  public void testOne() throws Exception {
    send("one");
  }

  @Test
  public void testTwo() throws Exception {
    send("two");
  }

  @Test
  public void testThree() throws Exception {
    send("three");
  }
}

When executed, the log "only final condition reaches here" is printed for final condition. When conditions are reordered also, it is printing for last condition.

I think it is a problem with Java DSL. When I created the same in XML, it works fine,

<camel:camelContext id="testCamelContext" trace="true"
        streamCache="true">
        <camel:route>
            <camel:from uri="direct:test" />
            <camel:choice>
                <camel:when>
                    <camel:simple>${header.number} == 'one'</camel:simple>
                    <camel:to uri="direct:one" />
                </camel:when>
        <camel:when>
          <camel:simple>${header.number} == 'two'</camel:simple>
          <camel:to uri="direct:two" />
        </camel:when>
        <camel:when>
          <camel:simple>${header.number} == 'three'</camel:simple>
          <camel:to uri="direct:three" />
        </camel:when>
            </camel:choice>
            <camel:to uri="bean:routeBean?method=receive" />
        </camel:route>
    </camel:camelContext>

Upvotes: 4

Views: 4251

Answers (2)

Peter Keller
Peter Keller

Reputation: 7636

In your example, the when conditions seem to evaluate correctly, however the final log statement is missing for test "one" and "two".

Use .end() instead of .endCoice():

  • Use .endChoice() in order to return "back" to the Content Based Router, i.e., use .endChoice() to end a when condition if the code block is not a simple statement, see here for more information about this problem.
  • Use .end() in order to end the whole choice block.

Upvotes: 7

Claus Ibsen
Claus Ibsen

Reputation: 55525

You are comparing a string likely with a class type, and that will always not match.

You can use the string values of those enum classes, so its

${header.foo} == 'FOO'

Only if the header is an actual enum class type the == comparator would work. But maybe we can improve Camel to detect that you are comparing against an enum type and attempt type conversions prior. I have logged a ticket: https://issues.apache.org/jira/browse/CAMEL-8485

Upvotes: 0

Related Questions