Babel provides mainly two ways to deal with errors : depending on if the handling is Exception specific or not. In any case, the error handling is done using the handle keyword.
Note
The error handling keywords, when defined in a route, are member of a set of keywords which should follow directly the from keyword or any keyword of this set.
This part concerns error handling which does not take into account the type of the raised exception. It just let you define strategies that are used for any raised exception:
The deadletter will send received exception to the defined endpoint.
from("direct:babel")
//Message causing exception would be sent to the deadletter
.handle(_.deadletter("mock:error").maximumRedeliveries(2))
The LoggingErrorHandler will just received exception to the defined logger at the defined logging level.
import org.apache.camel.LoggingLevel
import org.slf4j.LoggerFactory
from("direct:babel")
//logs raised Exception at the Trace level
.handle(_.loggingErrorHandler(level = LoggingLevel.TRACE,
logger = LoggerFactory.getLogger("my.cool.tata")))
.processBody(_ => throw new Exception())
.to("mock:success")
The default error handler is, as its name claims, implicit. This may be used to override inherited error handler.
from("direct:babel")
//The exchange may get redelivered twice before the Exception is raised higher
.handle(_.defaultErrorHandler.maximumRedeliveries(2))
The NoErrorHandler overrides errorhandling defined by a route which is given as input of the current route.
val masterRoutes = new RouteBuilder {
from("direct:babel")
.handle(_.on[IllegalArgumentException].continuedBody(true))
.to("direct:channel").to("mock:babel")
}
val errorRoutes = new RouteBuilder {
from("direct:channel")
//erase the error handling policy defined in the higher route
.handle(_.noErrorHandler)
.process(any => throw new IllegalArgumentException(s"blah:$any")).
to("mock:exception")
}
You may define specific error management depending on the type of the thrown exception using the on keyword:
The when parameter allows you to be more precise about the exception which should be process through this exception clause. In the below example, the exceptions which message contains “toto” are received in the output. The exceptions which message contains “tata” are handled but would not reach the output.
from("direct:input")
.handle {
route =>
//Message containing "toto" and causing an Exception should continue the route
route.onBody[Exception]((x: Any) => x.toString.contains("toto")).continuedBody(true)
//Message containing "tata" and causing an Exception should stop and the Exception
// should be tagged as handled
route.onBody[Exception]((x: Any) => x.toString.contains("tata")).handledBody(true)
.sub("exception").to("mock:exception")
}
The continued keyword allows to specify if the exchange should continue processing within the original route. The continued keyword accepts a Camel Predicate or a Boolean function.
from("direct:input")
.handle {
route =>
//Messages which causes IllegalArgumentException
route.on[IllegalArgumentException].
//are catch and continue the flow if body is "toto"
continuedBody((x: Any) => x.toString == "toto")
}
The handled keyword accepts a Camel Predicate or a Boolean function. If the parameter to handled keyword evaluates to true then the exception will not be raised with a caller:
from("direct:input")
.handle {
route =>
route.on[IllegalArgumentException].handledBody((x: Any) => x.toString.contains("toto"))
}
You may use the sub keyword to define a new route which should manage this exception
from("direct:input")
.handle {
//Any message which cases an IllegalArgumentException
_.on[IllegalArgumentException].
//should be transfered, via a sub route called "illegal-argument"
sub("illegal-argument").
//to the "mock:sub" endpoint (the sub route may also consists into more steps)s
to("mock:sub")
}
handle {
route =>
//Message raising Exception in any of the following route
// will be sent to the deadletter
route.deadletter("mock:error").maximumRedeliveries(2)
}
from("direct:blah").to("mock:blah")
from("direct:blih").to("mock:blih")
In the example above, the two routes send their exceptions to the mock:error endpoint.