I’ve been using Apache Camel more and more lately and one thing that has irritated me is creating a big project with maven, multiple classes etc for just a simple task. I thought Scala would be my savior, instead Groovy is.
This post shows how to get groovy scripts to block when stating up.
The examples I’ve seen on the web says that all you need is:
def camelCtx = new DefaultCamelContext()camelCtx.addRoutes(new SampleRoute())camelCtx.start()
(fromGroovy example: ActiveMQ broker and Apache Camel).
Somehow this didn’t work for me, and according to the very helpful guys on #camel it shouldn’t either.
What happens is that the start() method returns to the calling thread while starting up Camel in the background. The main thread then exits - thus shutting down everything.
I still do not understand how the examples are supposed to work - but I can hope to learn some day :)
According to Claus Ibsen on #camel (and one of the main commiters to the project), thecorrectway to get this to work is to implement a subclass of the abstract class MainSupport that creates the CamelContext and starts it.
There is one implementation of MainSupport in camel-spring that supports loading Spring contexts etc when starting a Camel route, but I wanted something much simpler that would work with as little fuss as possible.
Here’s what I came up with:
/*** This is a simple implementation of MainsSupport to handle running simple scripts* as camel services.** Note that the implementation only does one context.* @author Tarjei Huse,tarjei@scanmine.com**/public class GroovyMain extends MainSupport {CamelContext context = new DefaultCamelContext();public GroovyMain() {this.addChildService contextthis.camelContexts.add context}protected ProducerTemplate findOrCreateCamelTemplate() {return context.createProducerTemplate()}@Overrideprotected void doStart() throws Exception {super.doStart();//context.addRoutes this.getRouteBuilders()postProcessContext(); // does add routes}protected Map<String, CamelContext> getCamelContextMap() {return ['main': context]}/*** Add a component to the context* @param name* @param component*/public void addComponent(String name, Component component ) {this.context.addComponent(name, component);}public CamelContext getCamelContext() {return context;}protected ModelFileGenerator createModelFileGenerator() throws JAXBException {return null;}/*** Enables the hangup support. Gracefully stops by calling stop() on a* Hangup signal.*/public void enableHangupSupport() {HangupInterceptor interceptor = new HangupInterceptor(this);Runtime.getRuntime().addShutdownHook(interceptor);}}/*** A class for intercepting the hang up signal* and do a graceful shutdown of the Camel.* Taken from the camel-spring implementation of MainSupport.*/class HangupInterceptor extends Thread {MainSupport mainInstance;public HangupInterceptor(MainSupport main) {mainInstance = main;}@Overridepublic void run() {try {mainInstance.stop();} catch (Exception ex) {Logger.getLogger("Shutdown handler").warn(ex);}}}
The implementation only handles one simple camel context. It also adds support for adding components to the context.