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.
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.