Camel exception handling is very similar to Java. Oh yes we can start talking about exception handling in Java, Spring, Groovy and Scala just because Camel is integrated with multiple technologies already. I always prefer to see Camel as a product rather than an implementation. Some of my insights here:
<onException> and <doTry> are the key features to cover exceptions.
This can be used in two ways:
a) Global exception handler across the camel context – covering all routes
b) Exception handler per route
Any single ‘To’ endpoint / a processor / a set of endpoints and processors can be encapsulated in a doTry block.
3. Exception state – Handled / Continued
Handled: Terminate the camel flow + catch the exception + process the exchange to generate error messages / response message based on the requirement
Continued: Catch the exception + Process the exchange / Manipulate the exchange body + Continue the Camel flow
These three features are sufficient enough to cover exceptions in any complex integration flow. Apart from that options like Dead Letter Channel will be helpful to make exception handling more sophisticated.
There are certain conditions to be noted. Lets take this Route setup
- While using onException don’t expect it to work in a hierarchy based on route setup:
If you have a <onException> block in the parent route A looking for validation exceptions, this block will not catch validation exceptions thrown in child routes B/C.
In the below example: If validation exception is thrown in Route B, even though Route A exception handler is looking for java.lang.Exception ( parent of all exceptions ). This exception will be caught by the global exception handler outside the routes. The scope of java.lang.Exception handler is limited to Route A.
<camelContext xmlns="http://camel.apache.org/schema/spring"> <onException> <exception>org.apache.camel.ValidationException</exception> <handled><simple>true<simple></handled> <!-- error message processing --> </onException> <route id=“A-Parent”> <from uri=“cxf:ws-entry” /> <onException> <exception>java.lang.Exception</exception> <handled><simple>true<simple></handled> <!-- error message processing --> </onException> <to uri="direct:routeB-Handler" /> </route> <route id="B-Child1"> <from uri="direct:routeB-Handler" /> <throwException ref="CamelValidationException" /> <to uri="direct:routeC-Handler" /> </route> </camelContext><br>
2. Whereas in case of a <doTry>
In Route A – encapsulate the ‘To’ endpoint connecting to Route B with a <doTry>. This will let you catch exceptions thrown in Route B.
<route id=“A-Parent”> <from uri=“cxf:ws-entry” /> <doTry> <to uri="direct:routeB-Handler" /> <doCatch> <exception>org.apache.camel.ExchangeTimedOutException</exception> </doCatch> </doTry> </route> <route id="B-Child1"> <from uri="direct:routeB-Handler" /> <throwException ref="CamelExchangeTimeout" /> <to uri="direct:routeC-Handler" /> </route><br>
3. There can be 4 independent doTry blocks in each route catching different exceptions. After catching the exceptions, these blocks can be set to throw a common exception which can be further handled by a <onException> global exception handler
4. Functionally <exception>,<handled>,<continued> works the same way in <doTry> & <onException>
These are some of the basic points to keep in mind. There are multiple patterns possible with these features. Its purely based on what kind of exception handling framework you are trying to build in Camel projects.
If you use onException in parent route and expecting the child route exception to be propagated to parent route. You have to refer the child route to noErrorHandler.
Some useful links: