6 Replies Latest reply on Mar 4, 2013 10:11 AM by davsclaus

    how does camel error handling scope work

    jasonnh

      Hi,

       

      I am struggling to understand how error handlers work in camel and would appreciate any help.

       

      As an example, below is a camel context with four endpoints (ioExceptionProcessor simply throws an IOException)

       

      1]  activemq:route1

      This seems to ignore the dead letter error handler, i.e. no retries are attempted.

       

      2]  activemq:route2

      Works as expected although it is interesting that 'route2-A 1' is not output on the retries, i.e. the retry goes back to the point of failure rather than the whole route.

       

      3]  activemq:route3

      Introduces a doTry.  I was expecting this to behave like route2 but it behaves like route1 and ignores the error handler.

       

      4]  activemq:route4

      This does what I wanted route3 to do but I had to introduce an intermediate route (route4-A).

       

      Please can anybody spot what I am doing wrong?

       

      Thanks.

       

      <camelContext trace="false" id="testBlueprintContext" xmlns="http://camel.apache.org/schema/blueprint">
      
        <errorHandler useOriginalMessage="true" level="ERROR" deadLetterUri="activemq:test-dead"
          type="DeadLetterChannel" id="testDeadLetterErrorHandler">
          <redeliveryPolicy logStackTrace="true" retryAttemptedLogLevel="INFO"
            backOffMultiplier="2" redeliveryDelay="1000" maximumRedeliveries="5"></redeliveryPolicy>
        </errorHandler>
      
        <route id="route1" errorHandlerRef="testDeadLetterErrorHandler">
          <from uri="activemq:route1"></from>
          <log message="route1 1"></log>
          <to uri="direct:route1-A"></to>
          <log message="route1 2"></log>
        </route>
      
        <route id="route1-A" >
          <from uri="direct:route1-A"></from>
          <log message="route1-A 1"></log>
          <process ref="ioExceptionProcessor"></process>
          <log message="route1-A 2"></log>
        </route>
      
        <route id="route2">
          <from uri="activemq:route2"></from>
          <log message="route2 1"></log>
          <to uri="direct:route2-A"></to>
          <log message="route2 2"></log>
        </route>
      
        <route id="route2-A" errorHandlerRef="testDeadLetterErrorHandler">
          <from uri="direct:route2-A"></from>
          <log message="route2-A 1"></log>
          <process ref="ioExceptionProcessor"></process>
          <log message="route2-A 2"></log>
        </route>
      
        <route id="route3">
          <from uri="activemq:route3"></from>
          <log message="route3 1"></log>
          <to uri="direct:route3-A"></to>
          <log message="route3 2"></log>
        </route>
      
        <route id="route3-A" errorHandlerRef="testDeadLetterErrorHandler">
          <from uri="direct:route3-A"></from>
          <log message="route3-A 1"></log>
          <doTry>
            <process ref="ioExceptionProcessor"></process>
          <doCatch>
            <exception>java.io.IOException</exception>
            <handled>
              <constant>false</constant>
            </handled>
            <log message="route3-A 2"></log>
          </doCatch>
          <log message="route3-A 3"></log>
          </doTry>
        </route>
      
        <route id="route4">
          <from uri="activemq:route4"></from>
          <log message="route4 1"></log>
          <to uri="direct:route4-A"></to>
          <log message="route4 2"></log>
        </route>
      
        <route id="route4-A" errorHandlerRef="testDeadLetterErrorHandler">
          <from uri="direct:route4-A"></from>
          <log message="route4-A 1"></log>
          <to uri="direct:route4-B"></to>
          <log message="route4-A 2"></log>
        </route>
      
        <route id="route4-B">
          <from uri="direct:route4-B"></from>
          <log message="route4-B 1"></log>
          <doTry>
            <process ref="ioExceptionProcessor"></process>
            <doCatch>
              <exception>java.io.IOException</exception>
              <handled>
                <constant>false</constant>
              </handled>
              <log message="route4-B 2"></log>
            </doCatch>
            <log message="route4-B 3"></log>
          </doTry>
        </route>
      </camelContext>
      

      Edited by: jasonnh on Mar 1, 2013 9:52 AM

       

      Edited by: jasonnh on Mar 1, 2013 10:00 AM

        • 1. Re: how does camel error handling scope work
          davsclaus

          If you have a copy of Camel in Action book, then read chapter 5, its all about error handling.

          • 2. Re: how does camel error handling scope work
            davsclaus

            The error handler in your example is only active when the exchange is being routed in the 1st route. When you route to the other routes, then its the default error handler (which does nothing).

             

            So you need to either

            - configure error handler on CamelContext level to have it on all the routes

            - configure per route (route configure overrides CamelContext level)

            • 3. Re: how does camel error handling scope work
              jasonnh

              Thanks.  I have reread chapter 5.

               

              Just to correct myself:

               

              "Camel In Action" 5.3.2 page 133 describes that redelivery attempt is at the point of origin which explains why 'route2-A 1' is not part of the redelivery.

               

               

              "The error handler in your example is only active when the exchange is being routed in the 1st route. When you route to the other routes, then its the default error handler (which does nothing)."

               

               

              That explains activemq:route1 and activemq:route2 but I am still unclear about activemq:route3 and activemq:route4, i.e. why doTry causes different behaviour?

               

              The (excellent) book suggests using onException.  However, that does not help me achieve what I want which is for the error handler to only apply to IOException.  If I use onException then I can configure retries but not the dead letter part(?).

               

              I missed a part off my intended exception handling from my original post which is below.  I still do not understand why I need to introduce the intermediate route, i.e. why route3-A does not use the error handler?

               

              Thanks.

               

              <doCatch>
                <exception>java.io.IOException</exception>
                <handled>
                  <constant>false</constant>
                </handled>
                <log message="route4-B 2"></log>
              </doCatch>
              <doCatch>
                <exception>java.lang.Exception</exception>
                <log message="route4-B 3"></log>
              </doCatch>
              

               

              • 4. Re: how does camel error handling scope work
                davsclaus

                When you use doTry .. doCatch then any error handler is NOT in use.

                 

                And you can use onException to perform redeliveries, and when the exchange is exhausted your can handle it, and move it to a DLQ destination (eg it can be like a DLC also).

                • 5. Re: how does camel error handling scope work
                  jasonnh

                  Many thanks for your help with this.  I have another question though...

                   

                   

                  And you can use onException to perform redeliveries, and when the exchange is exhausted your can handle it, and move it to a DLQ destination (eg it can be like a DLC also).

                   

                   

                  My what can handle it?  If you are referring to the onException clause how do I tell if the exchange is exhausted rather than just another redelivery iteration?

                   

                  Edited by: jasonnh on Mar 4, 2013 10:05 AM

                  • 6. Re: how does camel error handling scope work
                    davsclaus

                    You can set maximumRedeliveries etc on the onExceptio nas well. So when all these redeliver attempts fails, then you can handle the exception and route it to your DLQ

                     

                    See more detail at

                    http://camel.apache.org/exception-clause.html

                     

                    You would need to mark handled=true as well, since you handle the exception by routing the message to your DLQ.