Camel development series part 7

In this post I will go through how I found a usefully way of handling asynchronous error handling when working with Apache Camel.

The requirements are as follows.

  1. We have a bunch of routes chained together who exist in different routeBuilder classes.
  2. The client does not require a response back so there is no need for an synchronous connection.
  3. We want a generic error handling strategy as we don’t want to replicate the error handling code in each routeBuilder class.

Essentially we want a global exception handler applied to all routeBuilder classes in a uniform way. Some months ago I faced the above requirements and googled a bit and found this post on stackoverflow:

http://stackoverflow.com/questions/9283861/camel-exception-handling-doesnt-work-if-exception-clause-is-defined-in-a-separat

This helped a lot accomplishing what I wanted. So let’s break it down:

Standard routeBuilder class

 

public class MyRouteBuilder extends RouteBuilder {
  
  @Override
  public void configure() throws Exception {
	ExceptionBuilder.setup(this);
	from()...to();
	}
}

Notice, that we have added the line

 ExceptionBuilder.setup(this);

which sends this instance of the RouteBuilder class to our ExceptionBuilder.

Now off course we need to create our ExceptionBuilder class. This is how I have done:

public class ExceptionBuilder {

    public static void setup(RouteBuilder routeBuilder) {
    routeBuilder.onException(Exception.class).useOriginalMessage().handled(true).to("direct://ErrorHandler");
  }  
}

I have created a standard java class which has a setup method accepting a RouteBuilder object as a parameter.

It then configures the .onException handling and directs the exchange to the ErrorHandler route. The configuration I have used is based on my needs, you can configure it your way. I want to listen for all possible exceptions, and use the original message and handle the exception which is why it looks like that. Now all we have left is to create our ErrorHandler route.

public class ErrorHandler extends RouteBuilder {

  @Override
  public void configure() throws Exception {
    String hashSeparator = "##################################################################################################################";
    String lineBreak = System.lineSeparator();
    from("direct://ErrorHandler").startupOrder(1).routeId("ErrorHandler")
      .log(LoggingLevel.ERROR, "ErrorHandler", hashSeparator)
      .log(LoggingLevel.ERROR, "ErrorHandler", "An error occured in the integration integration" + lineBreak)
      .setHeader("CamelMessageId", simple("${id}"))
      .setHeader("CamelContextId", simple("${camelId}"))
      .setHeader("CamelCreatedTimestamp", simple("${property.CamelCreatedTimestamp}"))
      .setHeader("CamelExceptionCaught", simple("Exception Object: ${property.CamelExceptionCaught}"))
      .setHeader("CamelStacktrace", simple("${exception.stacktrace}"))
      .setHeader("ExceptionMessage", simple("${exception.message}"))
      .setHeader("CamelFailureEndpoint", simple("${property.CamelFailureEndpoint}"))
      .setHeader("CamelFailureRouteId", simple("${property.CamelFailureRouteId}"))
      .log(LoggingLevel.ERROR, "ErrorHandler", " Headers: ${headers}" + lineBreak + lineBreak)
      .log(LoggingLevel.ERROR, "ErrorHandler", " Body: ${body}" + lineBreak)
      .log(LoggingLevel.ERROR, "ErrorHandler", hashSeparator);
  }
}

The ErrorHandler route is a normal route but with an explicit startup order and then I log a bunch of specific headers and set other headers. You can add and remove stuff as you please and as you want your error log output to look.

Combining the three steps we have seen gives us a powerful way to do error handling in a generic manner applied to all our RouteBuilder classes. This is especially useful for integrations where the client doesn’t need a response and the error handling is the same for all routes.
 

Annonser

Kommentera

Fyll i dina uppgifter nedan eller klicka på en ikon för att logga in:

WordPress.com Logo

Du kommenterar med ditt WordPress.com-konto. Logga ut / Ändra )

Twitter-bild

Du kommenterar med ditt Twitter-konto. Logga ut / Ändra )

Facebook-foto

Du kommenterar med ditt Facebook-konto. Logga ut / Ändra )

Google+ photo

Du kommenterar med ditt Google+-konto. Logga ut / Ändra )

Ansluter till %s