Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Configuring a global error handler for camel?

Tags:

apache-camel

I'm trying to configure an exception handler for all exceptions thrown by all routes in my camel context. My approach is the following, with no luck:

  1. Instantiate a default camel context
  2. Retrieve a list of RouteDefinition from a spring context
  3. Add these definitions to the camel context by calling ctx.addRouteDefinitions()
  4. Add my exception handler route from a java dsl defined RotueBuilder (ctx.addRoutes(new MyErrorHandlerRouteBuilder())
  5. Start the camel context

At this point, exceptions thrown inside the routes defined in spring are handled by the DefaultErrorHandler, not the one I'm trying to define. Here's what my error handling route definition looks like

public class MyErrorHandlerRouteBuilder extends RouteBuilder {
@Override
public void configure() throws Exception {
    onException(Exception.class)
        .routeId("errorHandlerRoute")
        .handled(true)
        .process(new Processor() {

            @Override
            public void process(Exchange exchange) throws Exception {
                Throwable caused = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, Throwable.class);
                // do some custom processing of the exception
            }
        })
        .stop();
}  

What else can I try, or where am I going wrong?

like image 820
Josiah Avatar asked Feb 14 '13 21:02

Josiah


3 Answers

Create an abstract base class and define your global error handler in the configure method. And then in your route classes extend this base class, and in their configure method call super.configure() first.

like image 90
Claus Ibsen Avatar answered Oct 24 '22 12:10

Claus Ibsen


For future readers, this is the solution that I use for camel error handling (This is all java config but it will work as spring xml):

1) Setup a DeadLetterChannelBuilder Bean

@Bean
public DeadLetterChannelBuilder myErrorHandler() {
    DeadLetterChannelBuilder deadLetterChannelBuilder = new DeadLetterChannelBuilder();
    deadLetterChannelBuilder.setDeadLetterUri("direct:error");
    deadLetterChannelBuilder.setRedeliveryPolicy(new RedeliveryPolicy().disableRedelivery());
    deadLetterChannelBuilder.useOriginalMessage();
    return deadLetterChannelBuilder;
}

Now this bean will be responsible for picking up errors and directing them to the direct:error URI.

2) Setup your error handling route

You will want a route to listen on the URI direct:error because this is where your errors are now being routed.

@Override
public void configure() throws Exception {
    from("direct:error")
            .to("log:error")
            .end();
}

As you can see now that all your errors are being routed to the above route you have the flexibility to implement complex error handling logic globally.

3) Inject your global error handler into your routes

You still need to inject your error handling bean into each route. I wish camel would handle this automatically but I have not found a way. Although with this approach the code duplication/overhead is minimal.

@Override
public void configure() throws Exception {
    errorHandler(myErrorHandler)
    from("myStartingUri")
            .to("myEndDestination")
            .end();
}

Looking at the documentation for springs xml based config I think you would need to put <route errorHandlerRef="myErrorHandler"> in your route definition.

like image 41
EricF Avatar answered Oct 24 '22 12:10

EricF


Error handlers are route builder specific in Java DSL. You need to create one per route builder. Or in your case, you need to define it in Spring DSL (as you seems to define your routes in Spring).

like image 34
Petter Nordlander Avatar answered Oct 24 '22 14:10

Petter Nordlander