CAMEL-11229: Mark exchange as circulr detected for error handler.

Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/bddcd40a
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/bddcd40a
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/bddcd40a

Branch: refs/heads/camel-2.19.x
Commit: bddcd40ab14ad5d8c8fe124674c1d9ff827d3e95
Parents: 7fda167
Author: Claus Ibsen <davscl...@apache.org>
Authored: Thu May 11 13:17:14 2017 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Thu May 11 18:39:49 2017 +0200

----------------------------------------------------------------------
 .../src/main/java/org/apache/camel/Exchange.java | 11 ++++++-----
 .../processor/FatalFallbackErrorHandler.java     | 19 ++++++++++++-------
 .../onexception/OnExceptionRecursionTest.java    | 10 ++++++----
 3 files changed, 24 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/bddcd40a/camel-core/src/main/java/org/apache/camel/Exchange.java
----------------------------------------------------------------------
diff --git a/camel-core/src/main/java/org/apache/camel/Exchange.java 
b/camel-core/src/main/java/org/apache/camel/Exchange.java
index 925e677..eecc7e0 100644
--- a/camel-core/src/main/java/org/apache/camel/Exchange.java
+++ b/camel-core/src/main/java/org/apache/camel/Exchange.java
@@ -111,11 +111,12 @@ public interface Exchange {
     
     String DOCUMENT_BUILDER_FACTORY = "CamelDocumentBuilderFactory";
 
-    String EXCEPTION_CAUGHT           = "CamelExceptionCaught";
-    String EXCEPTION_HANDLED          = "CamelExceptionHandled";
-    String EVALUATE_EXPRESSION_RESULT = "CamelEvaluateExpressionResult";
-    String ERRORHANDLER_HANDLED       = "CamelErrorHandlerHandled";
-    String EXTERNAL_REDELIVERED       = "CamelExternalRedelivered";
+    String EXCEPTION_CAUGHT              = "CamelExceptionCaught";
+    String EXCEPTION_HANDLED             = "CamelExceptionHandled";
+    String EVALUATE_EXPRESSION_RESULT    = "CamelEvaluateExpressionResult";
+    String ERRORHANDLER_CIRCUIT_DETECTED = "CamelFErrorHandlerCircuitDetected";
+    String ERRORHANDLER_HANDLED          = "CamelErrorHandlerHandled";
+    String EXTERNAL_REDELIVERED          = "CamelExternalRedelivered";
 
     String FAILURE_HANDLED      = "CamelFailureHandled";
     String FAILURE_ENDPOINT     = "CamelFailureEndpoint";

http://git-wip-us.apache.org/repos/asf/camel/blob/bddcd40a/camel-core/src/main/java/org/apache/camel/processor/FatalFallbackErrorHandler.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/main/java/org/apache/camel/processor/FatalFallbackErrorHandler.java
 
b/camel-core/src/main/java/org/apache/camel/processor/FatalFallbackErrorHandler.java
index b289bb7..9326062 100644
--- 
a/camel-core/src/main/java/org/apache/camel/processor/FatalFallbackErrorHandler.java
+++ 
b/camel-core/src/main/java/org/apache/camel/processor/FatalFallbackErrorHandler.java
@@ -24,6 +24,8 @@ import org.apache.camel.Processor;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import static org.apache.camel.builder.ExpressionBuilder.routeIdExpression;
+
 /**
  * An {@link org.apache.camel.processor.ErrorHandler} used as a safe fallback 
when
  * processing by other error handlers such as the {@link 
org.apache.camel.model.OnExceptionDefinition}.
@@ -52,25 +54,28 @@ public class FatalFallbackErrorHandler extends 
DelegateAsyncProcessor implements
     @Override
     @SuppressWarnings("unchecked")
     public boolean process(final Exchange exchange, final AsyncCallback 
callback) {
+        // get the current route id we use
+        final String id = routeIdExpression().evaluate(exchange, String.class);
+
         // prevent endless looping if we end up coming back to ourself
-        Stack<Processor> fatals = 
exchange.getProperty(Exchange.FATAL_FALLBACK_ERROR_HANDLER, null, Stack.class);
+        Stack<String> fatals = 
exchange.getProperty(Exchange.FATAL_FALLBACK_ERROR_HANDLER, null, Stack.class);
         if (fatals == null) {
             fatals = new Stack<>();
             exchange.setProperty(Exchange.FATAL_FALLBACK_ERROR_HANDLER, 
fatals);
         }
-        if (fatals.search(this) > -1) {
-            LOG.warn("Circular error-handler detected - breaking out 
processing Exchange: {}", exchange);
+        if (fatals.search(id) > -1) {
+            LOG.warn("Circular error-handler detected at route: {} - breaking 
out processing Exchange: {}", id, exchange);
             // mark this exchange as already been error handler handled (just 
by having this property)
             // the false value mean the caught exception will be kept on the 
exchange, causing the
             // exception to be propagated back to the caller, and to break out 
routing
             exchange.setProperty(Exchange.ERRORHANDLER_HANDLED, false);
+            exchange.setProperty(Exchange.ERRORHANDLER_CIRCUIT_DETECTED, true);
             callback.done(true);
             return true;
         }
 
         // okay we run under this fatal error handler now
-        final Processor fatal = this;
-        fatals.push(fatal);
+        fatals.push(id);
 
         // support the asynchronous routing engine
         boolean sync = processor.process(exchange, new AsyncCallback() {
@@ -137,9 +142,9 @@ public class FatalFallbackErrorHandler extends 
DelegateAsyncProcessor implements
                     }
                 } finally {
                     // no longer running under this fatal fallback error 
handler
-                    Stack<Processor> fatals = 
exchange.getProperty(Exchange.FATAL_FALLBACK_ERROR_HANDLER, null, Stack.class);
+                    Stack<String> fatals = 
exchange.getProperty(Exchange.FATAL_FALLBACK_ERROR_HANDLER, null, Stack.class);
                     if (fatals != null) {
-                        fatals.remove(fatal);
+                        fatals.remove(id);
                     }
                     callback.done(doneSync);
                 }

http://git-wip-us.apache.org/repos/asf/camel/blob/bddcd40a/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRecursionTest.java
----------------------------------------------------------------------
diff --git 
a/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRecursionTest.java
 
b/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRecursionTest.java
index bd12b0d..bac6e40 100644
--- 
a/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRecursionTest.java
+++ 
b/camel-core/src/test/java/org/apache/camel/processor/onexception/OnExceptionRecursionTest.java
@@ -53,8 +53,9 @@ public class OnExceptionRecursionTest extends 
ContextTestSupport {
 
         getMockEndpoint("mock:a").expectedMessageCount(1);
         getMockEndpoint("mock:b").expectedMessageCount(0);
-        getMockEndpoint("mock:c").expectedMessageCount(1);
-        getMockEndpoint("mock:d").expectedMessageCount(1);
+        // will be called twice because of the two exceptions because the 
circular exception is detected to break out
+        getMockEndpoint("mock:c").expectedMessageCount(2);
+        getMockEndpoint("mock:d").expectedMessageCount(2);
 
         try {
             template.sendBody("direct:test", "Hello World");
@@ -67,8 +68,7 @@ public class OnExceptionRecursionTest extends 
ContextTestSupport {
             assertEquals("Bad state", ise.getMessage());
         }
 
-        // TODO: should only trigger error handling in direct route one time
-        // assertMockEndpointsSatisfied();
+         assertMockEndpointsSatisfied();
     }
 
     public void testRecursionDirectNoErrorHandler() throws Exception {
@@ -94,6 +94,8 @@ public class OnExceptionRecursionTest extends 
ContextTestSupport {
 
         getMockEndpoint("mock:a").expectedMessageCount(1);
         getMockEndpoint("mock:b").expectedMessageCount(0);
+        // we will only be called once because when the route fails its not 
under error handler
+        // and therefore onException wont trigger the 2nd time
         getMockEndpoint("mock:c").expectedMessageCount(1);
         getMockEndpoint("mock:d").expectedMessageCount(1);
 

Reply via email to