Search code examples
error-handlingapache-cameldead-letter

Camel Dead Letter Channel Processor


Below is my camel route code

.errorHandler(deadLetterChannel("jmstx:queue:ErrorHandler")
  .useOriginalMessage()
  .maximumRedeliveries(1));

from("jmstx:queue:ErrorHandler")
  .log("Sending Exception to MyErrorProcessor")
  .bean(MyErrorProcessor.class);        

from("file:/E:/Target/").routeId("Route1")
  .setHeader("route1Header").constant("changed")
  .log(LoggingLevel.DEBUG, "Route1Logger", "Inside Route 1")
  .throwException(new MyException("E_MYERROR_01"))
  .to("file:/E:/Target/Done");

Below is MyErrorProcessor code

public void process(Exchange exchange) throws Exception {
        Exception e=(Exception)exchange.getProperty(Exchange.EXCEPTION_CAUGHT);
        e.printStackTrace();
        if(e instanceof MyException){
            MyCustomMessage myMsg=new MyCustomMessage(exchange);
            logger.error(((MyException) e).getErrorCode(),((MyException) e).getErrorDesc());
        }else{
            MyCustomMessage myMsg=new MyCustomMessage(exchange);            logger.error(myMsg.getFromRouteId(),e.getMessage());
        }
    }

My Logger not logging the errorcode which im sending as E_MYERROR_01

Is there anything wrong im doing in the errorHandler deadletterchannel??


Solution

  • Yes if jmstx refers to a JMS endpoint then it only transfers data from the message body / header - not exceptions stored as exchange properties. Also the data transferred needs to be compliant according to the JMS spec and that has limitations what you can send. Read about this at the Camel JMS documentation and from the JMS API javadoc from Oracle.

    If you want to send the stacktrace / exception to the jmstx endpoint you need to do a custom message translation and add the infromation somewhere in the message that becomes sent as a JMS Message. Maybe as a JMS header or something, and then stored as a String text. Then in the processor you cannot de-serialize that as a java exception type, but you have the data as just as a String.

    You can also instead use the processor before sending to the JMS which likely is easier.

    errorHandler(deadLetterChannel("direct:dead")
      .useOriginalMessage()
      .maximumRedeliveries(1)); 
    
    // route for dead letter where we log it before sending to JMS
    from("direct:dead")
      .log("Sending Exception to MyErrorProcessor")   
      .bean(MyErrorProcessor.class);
      .to("jmstx:queue:ErrorHandler");