Babel Camel Error management

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.

Handle keyword

Error handling handle can handle one or several error-handling

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.

General error handling

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:

general error-handling

the four error-handling policy we will have a look at and their configuration.

DeadLetter channel

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))

LoggingErrorHandler

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")

DefaultErrorHandler

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))

NoErrorHandler

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")
}

Exception clauses

You may define specific error management depending on the type of the thrown exception using the on keyword:

  • when the exception should be treated, which is the parameter of the on keyword
  • continued
  • handled
OnException clauses

when

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")
  }

continued

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")
  }

handled

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"))

  }

Sub routes

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")
  }

Configure several routes

Error handling for Routes and RouteBuilder

Every Error handling keyword may also be used for every route defined in the RouteBuilder by using the handle keyword as if it was the beginning of a route:

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.