Since we're on a major migration process of this website, some component documents here are out of sync right now. In the meantime you may want to look at the asciidoc in the repository: https://github.com/apache/camel/blob/master/README.md https://github.com/apache/camel/blob/master/components/readme.adoc

How can I stop a route from a route

The 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

  • 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.

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.

Error rendering macro 'code': Invalid value specified for parameter 'java.lang.NullPointerException'
// 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:

Error rendering macro 'code': Invalid value specified for parameter 'java.lang.NullPointerException'
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 route

In this example we use a separate Thread to stop the route, triggered from the route itself.

Error rendering macro 'code': Invalid value specified for parameter 'java.lang.NullPointerException'
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
    latch.await(5, TimeUnit.SECONDS);

    // 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:

Error rendering macro 'code': Invalid value specified for parameter 'java.lang.NullPointerException'
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
                                    } finally {
                                        // signal we stopped the route
                                        latch.countDown();
                                    }
                                }
                            };
                        }

                        // start the thread that stops this route
                        stop.start();
                    }
                }).to("mock:done");
            
            from("direct:bar").routeId("bar")
                .to("mock:bar");
        }
    };
}

Alternative solutions

Camel 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.

  • suspend/resume is faster than stop/start. For example a HTTP server will still run but deny any incoming requests.
    Where as if it was stopped the HTTP listener would have been stopped.
  • shutdown means the route is being removed from 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 Lifecycle.

You can also use the ControlBus component to let it stop/start routes.

See Also

© 2004-2015 The Apache Software Foundation.
Apache Camel, Camel, Apache, the Apache feather logo, and the Apache Camel project logo are trademarks of The Apache Software Foundation. All other marks mentioned may be trademarks or registered trademarks of their respective owners.
Graphic Design By Hiram