I'm trying to remove some boilerplate from routes in Camel.
For example, let's consider the two routes, which are similar and most of their inner stuff could be generated. I've created a component "template", which creates TemplateEndpoint
, and modifyed an XML config to use the template component.
A custom method TemplateEndpoint.generateRoute
(adding route definitions) is being called from StartupListener
(defined in TemplateEndpoint.setSuffix
).
So while Camel context starting, route definitions appear in the context, but the framework doesn't create route services for them and hence they don't get started.
How to start routes added in StartupListener
?
Probably I'm facing an XY problem, and you can advice me a better approach to do the trick (i.e. adding and starting routes on the fly).
Similar two routes
<route id="route_A">
<from uri="restlet:/another1?restletMethods=GET" />
<to uri="first:run_A" />
<to uri="second:jump_A" />
<to uri="third:fly_A" />
</route>
<route id="route_B">
<from uri="restlet:/another2?restletMethods=GET" />
<to uri="first:run_B" />
<to uri="second:jump_B" />
<to uri="third:fly_B" />
</route>
Modified XML
<route id="route_A">
<from uri="restlet:/another1?restletMethods=GET" />
<to uri="template://?suffix=A" />
</route>
<route id="route_B">
<from uri="restlet:/another2?restletMethods=GET" />
<to uri="template://?suffix=B" />
</route>
Endpoint
public class TemplateEndpoint extends DefaultEndpoint {
/* some methods omitted */
// this endpoint creates a DefaultProducer, which does nothing
public void setSuffix(final String suffix) throws Exception {
this.getCamelContext().addStartupListener(new StartupListener() {
@Override
public void onCamelContextStarted(CamelContext context, boolean alreadyStarted) throws Exception {
generateRoute(suffix)
.addRoutesToCamelContext(context);
}
});
}
private RouteBuilder generateRoute(final String suffix){
final Endpoint endpoint = this;
return new RouteBuilder() {
@Override
public void configure() throws Exception {
from(endpoint)
.to("first:run_" + suffix)
.to("second:jump_" + suffix)
.to("third:fly_" + suffix);
}
}
}
I would create a dynamic route builder e.g.
public class MyRouteBuilder extends RouteBuilder {
private String another;
private String letter;
public MyRouteBuilder(CamelContext context,String another, String letter) {
super(context);
this.another=another;
this.letter=letter;
}
@Override
public void configure() throws Exception {
super.configure();
from("restlet:/"+another+"?restletMethods=GET")
.to("first:run_"+letter)
.to("second:jump_"+letter)
.to("third:fly_"+letter);
}
}
and add it on some event e.g
public class ApplicationContextProvider implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext context)
throws BeansException {
camelContext=(CamelContext)context.getBean("mainCamelContext");
camelContext.addRoutes(new MyRouteBuilder(camelContext, "another1","A"));
camelContext.addRoutes(new MyRouteBuilder(camelContext, "another2","B"));
..