blob: 5e62d2beb4582715814a2a24873eff980955db7e [file] [log] [blame]
= 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.
====