Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: updated and restructed

...

You can use the Exception Clause in the Java DSL to specify the error handling you require on a per exception type basis using the onException() method.

To get started we give quick sample before digging into how it works.
For example if you want to perform a specific piece of processing if a certain exception is raised you can do this simply via:

Code Block
onException(ValidationException.class).
  to("activemq:validationFailed");
  
from("seda:inputA").
  to("validation:foo/bar.xsd", "activemq:someQueue");

from("seda:inputB").to("direct:foo").
  to("rnc:mySchema.rnc", "activemq:anotherQueue");

Here if the processing of seda:inputA or seda:inputB cause a ValidationException to be thrown (such as due to the XSD validation of the Validation component or the Relax NG Compact syntax validation of the Jing component), then the message will be sent to activemq:validationFailed queue.

How does Camel select which clause should handle a given thrown Exception

Camel uses DefaultExceptionPolicyStrategy to determine a strategy how an exception being thrown should be handled by which onException clause. The strategy is:

  • the order in which the onException is configured takes precedence. Camel will test from first...last defined.
  • Camel will start from the bottom (nested caused by) and recursive up in the exception hierarchy to find the first matching onException clause
  • instanceof test is used for testing the given exception with the onException clause defined exception list. An exact instanceof match will always be used, otherwise the onException clause that has an exception that is the closets super of the thrown exception is selected (recurring up the exception hierarchy)

This is best illustrated with an exception:

...


onException(IOException.class).maximumRedeliveries(3);

onException(OrderFailedException.class).maximumRedeliveries(2);

You can define multiple onException clauses for different behavior

Code Block
java
java

onException(ValidationException.class).
  to("activemq:validationFailed");

onException(ShipOrderException.class).
  to("activemq:shipFailed");

from("seda:order").to("bean:processOrder");

Scopes

Exception clauses is scoped as either:

  • global
  • or route specific

Where the global are the simplest and most easy to understand. In the advanced section we dig into the route specific and even combining them. However

How does Camel select which clause should handle a given thrown Exception

Camel uses DefaultExceptionPolicyStrategy to determine a strategy how an exception being thrown should be handled by which onException clause. The strategy is:

  • the order in which the onException is configured takes precedence. Camel will test from first...last defined.
  • Camel will start from the bottom (nested caused by) and recursive up in the exception hierarchy to find the first matching onException clause
  • instanceof test is used for testing the given exception with the onException clause defined exception list. An exact instanceof match will always be used, otherwise the onException clause that has an exception that is the closets super of the thrown exception is selected (recurring up the exception hierarchy)

This is best illustrated with an exception:

Code Block
java
java

onException(IOException.class).maximumRedeliveries(3);

onException(OrderFailedException.class).maximumRedeliveries(2);

In the sample above we have defined two exceptions in which IOException is first, so Camel will pickup this exception if there is a match. IOException that is more general is selected then.

So if an exception is thrown with this hierarchy:

Code Block

+ RuntimeCamelException (wrapper exception by Camel)
   + OrderFailedException 
       + IOException
            + FileNotFoundException

In the sample above we have defined two exceptions in which IOException is first, so Camel will pickup this exception if there is a match. IOException that is more general is selected then.

So if an exception is thrown with this hierarchy:

Code Block

+ RuntimeCamelException (wrapper exception by Camel)
   + OrderFailedException 
       + IOException
            + FileNotFoundException

Then Camel will try testing the exception in this order: FileNotFoundException, IOException, OrderFailedException and RuntimeCamelException.
As we have defined a onException(IOException.class) Camel will select this as it's the closest match.

...

The default error handler used in Camel is the Dead Letter Channel which supports attempting to redeliver the message exchange a number of times before sending it to a dead letter endpoint.
See Dead Letter Channel for further information about redeliver and which redeliver options exists.

Sometimes you want to configure the redelivery policy on a per exception type basis. By default in the first examples, if a ValidationException occurs then the message will not be redelivered; however if some other exception occurs (such as a JDBC deadlock or remote method invocation) the route will be retried.

...

Advanced Usage of Exception Clause

Using global and per route exception clauses

Camel supports quite advanced configuration of exception clauses

...

.

You can define exception clauses either as:

  • global
  • or route specific

We start off with the sample sample that we change over time. First off we use only global exception clauses:

Wiki Markup
{snippet:id=e1|lang=java|url=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRouteTest.java}

In the next sample we change the global exception policies to be pure route specific.

Info
titleMust use .end() for route specific exception policies

Important: This requires to end the onException route with .end() to indicate where it stops and when the regular route continues.

Wiki Markup
{snippet:id=e1|lang=java|url=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionSubRouteTest.java}

And now it gets complex as we combine global and route specific exception policies as we introduce a 2nd route in the sample:

Wiki Markup
{snippet:id=e1|lang=java|url=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionComplexRouteTest.java}

Notice that we can define the same exception MyFunctionalException in both routes, but they are configured differently and thus is handled different depending on the route. You can of course also add a new onException to one of the routes so it has an additional exception policy.

And finally we top this by throwing in a nested error handler as well, as we add the 3rd route shown below:

Wiki Markup
{snippet:id=e1|lang=java|url=activemq/camel/trunk/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionComplexWithNestedErrorHandlerRouteTest.java}
Info
titleGlobal exception policies and nested error handlers

The sample above with both nested error handlers and both global and per route exception clauses is a bit advanced. It's important to get the fact straight that the global exception clauses is really global so they also applies for nested error handlers. So if a MyTechnicalException is thrown then it's the global exception policy that is selected.

Using fine grained selection using onWhen predicate

...