First, yes, I have searched and, yes, I have read the same Apache document every one points to. :-) I think there is a bit of confusion and I think I know an answer, so let me lay out an example of what I thought was correct, follow it with what I think the answer is. Thanks. Oh, and I do know that some of the endChoice() lines are not strictly necessary and that Camel will figure it out, but I like the blocks to be cleanly delineated, unless there is some reason not to use them.
.choice()
.when(X1)
// do stuff
.choice()
.when(Y)
//do more stuff
.endChoice() // close inner when block
.end() // close inner choice block
.endChoice() // close first outer when
.when(X2)
// do other stuff
.endChoice() // close second outer when
.end() // close outer choice
So, my original look at the API, I thought that end() was for closing things like choice and split and that endChoice() was for closing choice options like when and otherwise. It looks more like the latter is actually an end() that returns a ChoiceDefinition. Which makes the name a little better.
But, if I take out the end() labeled 'close inner choice block', this means I carry on to the next line, an endChoice(). Does this then close the inner choice block? Given that, the when(X2) is still within the the when(X1) block. So, I think that I need to replace the end() with an endChoice() rather than removing it. So the result would look like:
.choice()
.when(X1)
// do stuff
.choice()
.when(Y)
//do more stuff
.endChoice() // close inner when block
.endChoice() // close inner choice block
.endChoice() // close first outer when
.when(X2)
// do other stuff
.endChoice() // close second outer when
.end() // close outer choice
So is this the way to handle this in Camel? Or is there a simpler way that I am just missing? Thanks for your time.
. end() --> to close the entire "choice" block.
Purpose of 'Apache Camel' is to route 'messages' from one 'system' to another one in the world. Apache camel uses different transport mechanisms for message routing. Apache Camel picks up messages using 'Camel based Component' of the 'from' system and drops them using the 'Camel based Component' of the 'to' system.
The RouteBuilder is a base class which is derived from to create routing rules using the DSL. Instances of RouteBuilder are then added to the CamelContext .
The stop/start approach will do a cold restart of Camel, where all internal state is reset. End users are advised to use suspend/resume. Using stop is for shutting down Camel and it's not guaranteed that when it's being started again using the start method that Camel will operate consistently.
SHORT ANSWER: I will call myself on this so no one else has to, the answer is that you are doing it wrong and should not have nested choices.
LONG ANSWER: I inherited a complicated route builder and was trying to clean it up to make it clearer. But straightening and putting in either end() or endChoice() just broke things. And, yes, the above fix still broke things. I did not understand how Camel knew which block to go to. Research and trying to find good examples of nesting eventually drove home the fact that Camel is not really designed for nesting choices. It allows it, but due to limitations in Java, it does not do it well. So I tried removing my nested choices. While this would have been possible, it would have meant ugly redundant conditionals, like:
choice()
.when(x and a)
//do stuff xa
.when(x not a)
// do other x stuff
.when(y and a)
// do y stuff
Only mine would have had at least another level. Further thought and recalling things that I had read brought about the second bit of enlightenment. The whole point of Camel is directing routes. Each choice's when block should just be pointing the process to a route. It should not be thinking, processing, or anything. In the end, our group is going to be refactoring to remove most of the logic from the route builder to a bean. The design we will be working towards will be something simple:
from(uri)
.bean(class, method) // do any processing
.choice()
.when(header("result").isEqualTo("A")
.to(routeA)
.endChoice()
.when(header("result").isEqualTo("B")
.to(routeB)
.endChoice()
.when(header("result").isEqualTo("C")
.to(route)
.endChoice()
.end()
My advice to you is to avoid nesting choices. Particularly complicated ones. You might get it to work, but you will not be able to trust it when you have to make changes later. If you find yourself tempted to use nested choices, examine what you are trying to accomplish and decide if it really belongs in a route builder.
Coming late in the game, but might help.
Nested choice definitions work just fine with Camel. Only your terminators are wrong:
.endChoice()
--> to close a "when" predicate.end()
--> to close the entire "choice" blockI know, the syntax is a bit confusing.
So in your case:
.choice()
.when(X1)
// do stuff
.choice()
.when(Y)
//do more stuff
.endChoice() // close Y condition
.end() // close inner choice block
.endChoice() // close X1 condition
.when(X2)
// do other stuff
.endChoice() // close X2 condition
.otherwise()
// default case
.endChoice() // close default condition
.end()
In practice, you don't have to close all when
predicates, only for multiple child routings. In my humble opinion, being super meticulous with the indentation helps a lot.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With