How can I stop a route from a routeThe CamelContext provides API for managing routes at runtime. It has a stopRoute(id) and startRoute(id) methods. Stopping a route during routing an existing message is a bit tricky. The reason for that is Camel will Graceful Shutdown the route you are stopping. And if you do that while a message is being routed the Graceful Shutdown will try to wait until that message has been processed. The best practice for stopping a route from a route, is to either
Using another thread to stop the route is also what is normally used when stopping Camel itself, or for example when an application in a server is stopped etc. Its too tricky and hard to stop a route using the same thread that currently is processing a message from the route. This is not advised to do, and can cause unforeseen side effects. Using a latch to stop Camel from a routeIn this example we use a CountdownLatch to signal when Camel should stop, triggered from a route. // use a latch as signal when to stop Camel private final CountDownLatch latch = new CountDownLatch(1); public void testStopCamelFromRoute() throws Exception { // create camel, add routes, and start camel CamelContext context = new DefaultCamelContext(); context.addRoutes(createMyRoutes()); context.start(); // setup mock expectations for unit test MockEndpoint start = context.getEndpoint("mock:start", MockEndpoint.class); start.expectedMessageCount(1); MockEndpoint done = context.getEndpoint("mock:done", MockEndpoint.class); done.expectedMessageCount(1); // send a message to the route ProducerTemplate template = context.createProducerTemplate(); template.sendBody("direct:start", "Hello Camel"); // wait for the latch (use 1 minute as fail safe, due unit test) assertTrue(latch.await(1, TimeUnit.MINUTES)); // stop camel context.stop(); // unit test assertions start.assertIsSatisfied(); done.assertIsSatisfied(); } And in the route we call the latch as shown: public RouteBuilder createMyRoutes() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { from("direct:start").routeId("myRoute") .to("mock:start") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { // stop Camel by signalling to the latch latch.countDown(); } }).to("mock:done"); } }; } Using a thread to stop a route from a routeIn this example we use a separate Thread to stop the route, triggered from the route itself. public void testStopRouteFromRoute() throws Exception { // create camel, add routes, and start camel CamelContext context = new DefaultCamelContext(); context.addRoutes(createMyRoutes()); context.start(); assertTrue("Route myRoute should be started", context.getRouteStatus("myRoute").isStarted()); assertTrue("Route bar should be started", context.getRouteStatus("bar").isStarted()); // setup mock expectations for unit test MockEndpoint start = context.getEndpoint("mock:start", MockEndpoint.class); start.expectedMessageCount(1); MockEndpoint done = context.getEndpoint("mock:done", MockEndpoint.class); done.expectedMessageCount(1); // send a message to the route ProducerTemplate template = context.createProducerTemplate(); template.sendBody("direct:start", "Hello Camel"); // just wait a bit for the thread to stop the route Thread.sleep(1500); // the route should now be stopped assertTrue("Route myRoute should be stopped", context.getRouteStatus("myRoute").isStopped()); assertTrue("Route bar should be started", context.getRouteStatus("bar").isStarted()); // stop camel context.stop(); // unit test assertions start.assertIsSatisfied(); done.assertIsSatisfied(); } And in the route we create the thread and call the stopRoute method as shown: public RouteBuilder createMyRoutes() throws Exception { return new RouteBuilder() { @Override public void configure() throws Exception { from("direct:start").routeId("myRoute") .to("mock:start") .process(new Processor() { Thread stop; @Override public void process(final Exchange exchange) throws Exception { // stop this route using a thread that will stop // this route gracefully while we are still running if (stop == null) { stop = new Thread() { @Override public void run() { try { exchange.getContext().stopRoute("myRoute"); } catch (Exception e) { // ignore } } }; } // start the thread that stops this route stop.start(); } }).to("mock:done"); from("direct:bar").routeId("bar") .to("mock:bar"); } }; } Alternative solutionsCamel provides another feature for managing routes at runtime which is RoutePolicy. And CamelContext also provides API for suspend/resume of routes, and shutdown as well.
See more details about the Lifecycle. See Also |