|  | = How can I stop a route from a route | 
|  |  | 
|  | The xref:ROOT:camelcontext.adoc[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 xref:ROOT:graceful-shutdown.adoc[Graceful | 
|  | Shutdown] the route you are stopping. And if you do that while a message | 
|  | is being routed the xref:ROOT:graceful-shutdown.adoc[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: | 
|  |  | 
|  | * signal to another thread to stop the route | 
|  | * spin off a new thread to stop the route | 
|  |  | 
|  | 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. | 
|  |  | 
|  | [[HowcanIstoparoutefromaroute-UsingalatchtostopCamelfromaroute]] | 
|  | == Using a latch to stop Camel from a route | 
|  |  | 
|  | In this example we use a `CountdownLatch` to signal when Camel should | 
|  | stop, triggered from a route. | 
|  |  | 
|  | [source,java] | 
|  | ---- | 
|  | // 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: | 
|  |  | 
|  | [source,java] | 
|  | ---- | 
|  | 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"); | 
|  | } | 
|  | }; | 
|  | } | 
|  | ---- | 
|  |  | 
|  | [[HowcanIstoparoutefromaroute-Usingathreadtostoparoutefromaroute]] | 
|  | == Using a thread to stop a route from a route | 
|  |  | 
|  | In this example we use a separate `Thread` to stop the route, triggered | 
|  | from the route itself. | 
|  |  | 
|  | [source,java] | 
|  | ---- | 
|  | 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(1000); | 
|  |  | 
|  | // 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: | 
|  |  | 
|  | [source,java] | 
|  | ---- | 
|  | 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().getRouteController().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"); | 
|  | } | 
|  | }; | 
|  | } | 
|  | ---- | 
|  |  | 
|  | [[HowcanIstoparoutefromaroute-Alternativesolutions]] | 
|  | == Alternative solutions | 
|  |  | 
|  | Camel provides another feature for managing routes at runtime which is | 
|  | xref:ROOT:route-policy.adoc[RoutePolicy]. | 
|  |  | 
|  | And xref:ROOT:camelcontext.adoc[CamelContext] also provides API for | 
|  | suspend/resume of routes, and shutdown as well. | 
|  |  | 
|  | * suspend/resume is faster than stop/start. For example a HTTP server | 
|  | will still run but deny any incoming requests. | 
|  | Whereas if it was stopped the HTTP listener would have been stopped. | 
|  | * shutdown means the route is being removed from | 
|  | xref:ROOT:camelcontext.adoc[CamelContext] and cannot be started again. Its | 
|  | also removed from JMX. | 
|  | A route must have been stopped prior to be shutdown. | 
|  |  | 
|  | See more details about the xref:ROOT:lifecycle.adoc[Lifecycle]. | 
|  |  | 
|  | [NOTE] | 
|  | ==== | 
|  | You can also use the xref:components::controlbus-component.adoc[ControlBus] component to let | 
|  | it stop/start routes. | 
|  | ==== | 
|  |  |