[[HowcanIstoparoutefromaroute-HowcanIstoparoutefromaroute]]
= 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().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.
====

