Route Configuration! = Route Execution
It seems that you are confusing route configuration with route execution. We were all there ,-)
When you configure RouteBuilder in MainRouteBuilder#configure() , the method only executes once the Camel application loads to configure the routing logic. DSL creates plumbing for the route (Processors, Interceptors, etc.) and what will be the runtime of the route.
Point to return home: DSL is not executed again and again with each Exchange.
In other words, Camel does not do what you specify in (3). It does not execute new RouteContainer().getMyRoute(2) for each individual Exchange. Think about it: the bytecode for configure() only runs when Camel is configured, and the bytecode creates an instance of an object of the RouteContainer class and calls getMyRoute with argument 2 . The resulting object is SendProcessor to SendProcessor , which generates DSL to() .
Analysis of your code
Now about why your code does not give the expected result.
You are having trouble maintaining the state of the RouteContainer . Each time you call getMyRoute , you overwrite the route instance variable. Therefore, it is impossible for your current code to call getMyRoute several times (with different n s), and then call includeRoutes only once at the end, because only the last created route will be added.
I also don't like to mask the Camel route class with my own class, just to act as a placeholder, but this brings up another discussion that you didn't ask for.
Simplified solution
Instead of the RouteContainer class, here is the RouteGenerator class that creates routes and returns the direct: endpoint to the caller. It tracks all routes in the internal Set .
public class RouteGenerator { private Set<RouteBuilder> routeBuilders = new HashSet<>(); public String generateRoute(final int n) { routeBuilders.add(new RouteBuilder() { @Override public void configure() throws Exception { System.out.println("Building nested route!"); System.out.println("Context: " + getContext()); from("direct:myRoute." + n) .transform() .simple("number: " + n) .to("stream:out") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { Response response = new Response(); response.setStatus(Status.SUCCESS); exchange.getOut().setBody(response); } }); } }); return "direct:myRoute." + n; } public Set<RouteBuilder> getRouteBuilders() { return routeBuilders; } }
And here is your MainRouteBuilder , which creates an instance of RouteGenerator only once and can generate as many routes as you like.
As soon as you finish configuring routes, you simply RouteBuilders over the accumulated RouteBuilders and turn them on:
public class MainRouteBuilder extends RouteBuilder { public static CamelContext camelContext; public static RouteGenerator routeGenerator = new RouteGenerator(); @Override public void configure() throws Exception { System.out.println("Building main route!"); System.out.println("Context: " + getContext()); camelContext = getContext(); from("direct:mainRoute") .to(routeGenerator.generateRoute(2)); for (RouteBuilder routeBuilder : routeGenerator.getRouteBuilders()) { includeRoutes(routeBuilder); } } }
EDIT: Why is your option (2) not working?
After debugging for some time, I realized why you see this effect.
Extracted from the Java tutorial :
As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to this methods and object fields.
In (2), you create a route instance within the scope of the original RouteContainer object, acting as an external object. The route object saves the external RouteContainer as its external object. Therefore, from() and the following methods call this initial RouteContainer ( RouteBuilder ) object, not the new RouteContainer that you create later , which is the one you provide the top RouteBuilder (which is associated with CamelContext).
This is why your direct:myRoute.2 not added to the Camel Context because it is created in another route builder.
Also note that console output (2):
Building main route! Context: CamelContext(camel-1) Building nested route! Context: CamelContext(camel-2) Added!
The second route is added to another camel-2 context. Landl creates this new context lazily when he adds a route to an old RouteBuilder that has not yet been associated with any Camel loop.
Note that the Camel Context of the original RouteContainer (created by initializing the instance variable) is null , since you will later assign the MainRouteBuilder.camelContext property.
You can see how two different route builders are used by adding the following println statements:
Inside Route # configure:
System.out.println("RouteContainer to which route is added: " + RouteContainer.this.hashCode());
Inside MainRouteBuilder # configure, before includeRoutes :
System.out.println("RouteContainer loaded into Camel: " + nestedRouteBuilder.hashCode());
With (1) the hash code is the same as . With (2), the hash code is different , which clearly shows that the game has two different RouteBuilders players (one of which contains a route and one that is loaded into a context that does not include a route).
Source: I am a member of the Apache Camel PMC and committer.