Why can I not use when/otherwise in a Java Camel route?
When using the Content Based Router in
the Java DSL you may have a situation where the compiler will not accept
the following when()
or otherwise()
statement.
Quick tip Use |
For example as shown in the route below where we use the Load Balancer inside the Content Based Router in the first when:
Code will not compile
from("direct:start")
.choice()
.when(body().contains("Camel"))
.loadBalance().roundRobin().to("mock:foo").to("mock:bar")
.otherwise()
.to("mock:result");
Well the first issue is that the Load Balancer uses the additional routing to know what to use in the load balancing. In this example that would be the:
.to("mock:foo").to("mock:bar")
To indicate when the balancing stops, you should use .end()
to denote
the end. So the route is updates as follows:
Code will still not compile
from("direct:start")
.choice()
.when(body().contains("Camel"))
.loadBalance().roundRobin().to("mock:foo").to("mock:bar").end()
.otherwise()
.to("mock:result");
But the code will still not compile. The reason is we have stretched how
far we can take the good old Java language in terms of
DSL. In a more modern language such as
Scala or Groovy you would be able
to let it be stack based, so the .end()
will pop the last type of the
stack, and you would return back to the scope of the
Content Based Router. However that’s not
easily doable in Java. So we need to help Java a bit, which you do by
using .endChoice()
, which tells Camel to "pop the stack" and return
back to the scope of the Content Based
Router.
Code compiles
from("direct:start")
.choice()
.when(body().contains("Camel"))
.loadBalance().roundRobin().to("mock:foo").to("mock:bar").endChoice()
.otherwise()
.to("mock:result");
You only need to use .endChoice()
when using certain
EIPs which often have additional
methods to configure or as part of the
EIP itself. For example the
Splitter EIP has a sub-route which denotes the
routing of each split message. You would also have to use
.endChoice()
to indicate the end of the sub-route and to return back
to the Content Based Router.