This is an automated email from the ASF dual-hosted git repository.

nferraro pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel.git


The following commit(s) were added to refs/heads/master by this push:
     new b9c4f01  CAMEL-12555: fix saga behavior when expression evaluation 
fails
b9c4f01 is described below

commit b9c4f014b3588c98c369f752bcfd8835ee7063a9
Author: nferraro <ni.ferr...@gmail.com>
AuthorDate: Thu Jun 7 16:46:22 2018 +0200

    CAMEL-12555: fix saga behavior when expression evaluation fails
---
 .../camel/impl/saga/InMemorySagaCoordinator.java      |  6 +++++-
 .../camel/processor/saga/RequiredSagaProcessor.java   |  4 ++--
 .../processor/saga/RequiresNewSagaProcessor.java      |  4 ++--
 .../apache/camel/processor/saga/SagaProcessor.java    | 10 +++++++++-
 .../org/apache/camel/processor/SagaOptionsTest.java   | 19 ++++++++++++++++---
 .../apache/camel/service/lra/LRASagaCoordinator.java  |  7 ++++++-
 .../org/apache/camel/service/lra/LRASagaStep.java     |  7 ++++++-
 .../org/apache/camel/service/lra/LRAOptionsIT.java    | 11 +++++++++++
 8 files changed, 57 insertions(+), 11 deletions(-)

diff --git 
a/camel-core/src/main/java/org/apache/camel/impl/saga/InMemorySagaCoordinator.java
 
b/camel-core/src/main/java/org/apache/camel/impl/saga/InMemorySagaCoordinator.java
index 2fc5c2a..1d3f44e 100644
--- 
a/camel-core/src/main/java/org/apache/camel/impl/saga/InMemorySagaCoordinator.java
+++ 
b/camel-core/src/main/java/org/apache/camel/impl/saga/InMemorySagaCoordinator.java
@@ -84,7 +84,11 @@ public class InMemorySagaCoordinator implements 
CamelSagaCoordinator {
             Map<String, Object> values = optionValues.get(step);
             for (String option : step.getOptions().keySet()) {
                 Expression expression = step.getOptions().get(option);
-                values.put(option, expression.evaluate(exchange, 
Object.class));
+                try {
+                    values.put(option, expression.evaluate(exchange, 
Object.class));
+                } catch (Exception ex) {
+                    return CompletableFuture.supplyAsync(() -> {throw new 
RuntimeCamelException("Cannot evaluate saga option '" + option + "'", ex);});
+                }
             }
         }
 
diff --git 
a/camel-core/src/main/java/org/apache/camel/processor/saga/RequiredSagaProcessor.java
 
b/camel-core/src/main/java/org/apache/camel/processor/saga/RequiredSagaProcessor.java
index 7b77642..ddf4c3b 100644
--- 
a/camel-core/src/main/java/org/apache/camel/processor/saga/RequiredSagaProcessor.java
+++ 
b/camel-core/src/main/java/org/apache/camel/processor/saga/RequiredSagaProcessor.java
@@ -49,9 +49,9 @@ public class RequiredSagaProcessor extends SagaProcessor {
                 inheritedCoordinator = false;
             }
 
-            coordinatorFuture.whenComplete((coordinator, ex2) -> 
ifNotException(ex2, exchange, callback, () -> {
+            coordinatorFuture.whenComplete((coordinator, ex2) -> 
ifNotException(ex2, exchange, !inheritedCoordinator, coordinator, 
existingCoordinator, callback, () -> {
                 setCurrentSagaCoordinator(exchange, coordinator);
-                coordinator.beginStep(exchange, step).whenComplete((done, ex3) 
-> ifNotException(ex3, exchange, callback, () -> {
+                coordinator.beginStep(exchange, step).whenComplete((done, ex3) 
-> ifNotException(ex3, exchange, !inheritedCoordinator, coordinator, 
existingCoordinator, callback, () -> {
                     super.process(exchange, doneSync -> {
                         if (!inheritedCoordinator) {
                             // Saga starts and ends here
diff --git 
a/camel-core/src/main/java/org/apache/camel/processor/saga/RequiresNewSagaProcessor.java
 
b/camel-core/src/main/java/org/apache/camel/processor/saga/RequiresNewSagaProcessor.java
index a87fb55..e3d3d96 100644
--- 
a/camel-core/src/main/java/org/apache/camel/processor/saga/RequiresNewSagaProcessor.java
+++ 
b/camel-core/src/main/java/org/apache/camel/processor/saga/RequiresNewSagaProcessor.java
@@ -36,10 +36,10 @@ public class RequiresNewSagaProcessor extends SagaProcessor 
{
     @Override
     public boolean process(Exchange exchange, AsyncCallback callback) {
         getCurrentSagaCoordinator(exchange).whenComplete((existingCoordinator, 
ex) -> ifNotException(ex, exchange, callback, () ->
-                sagaService.newSaga().whenComplete((newCoordinator, ex2) -> 
ifNotException(ex2, exchange, callback, () -> {
+                sagaService.newSaga().whenComplete((newCoordinator, ex2) -> 
ifNotException(ex2, exchange, true, newCoordinator, existingCoordinator, 
callback, () -> {
                     setCurrentSagaCoordinator(exchange, newCoordinator);
 
-                    newCoordinator.beginStep(exchange, 
step).whenComplete((done, ex3) -> ifNotException(ex3, exchange, callback, () -> 
{
+                    newCoordinator.beginStep(exchange, 
step).whenComplete((done, ex3) -> ifNotException(ex3, exchange, true, 
newCoordinator, existingCoordinator, callback, () -> {
                         // Always finalizes the saga
                         super.process(exchange, doneSync -> 
handleSagaCompletion(exchange, newCoordinator, existingCoordinator, callback));
                     }));
diff --git 
a/camel-core/src/main/java/org/apache/camel/processor/saga/SagaProcessor.java 
b/camel-core/src/main/java/org/apache/camel/processor/saga/SagaProcessor.java
index ccd239c..95b94f2 100644
--- 
a/camel-core/src/main/java/org/apache/camel/processor/saga/SagaProcessor.java
+++ 
b/camel-core/src/main/java/org/apache/camel/processor/saga/SagaProcessor.java
@@ -98,9 +98,17 @@ public abstract class SagaProcessor extends 
DelegateAsyncProcessor {
     }
 
     protected void ifNotException(Throwable ex, Exchange exchange, 
AsyncCallback callback, Runnable code) {
+        ifNotException(ex, exchange, false, null, null, callback, code);
+    }
+
+    protected void ifNotException(Throwable ex, Exchange exchange, boolean 
handleCompletion, CamelSagaCoordinator coordinator, CamelSagaCoordinator 
previousCoordinator, AsyncCallback callback, Runnable code) {
         if (ex != null) {
             exchange.setException(ex);
-            callback.done(false);
+            if (handleCompletion) {
+                handleSagaCompletion(exchange, coordinator, 
previousCoordinator, callback);
+            } else {
+                callback.done(false);
+            }
         } else {
             code.run();
         }
diff --git 
a/camel-core/src/test/java/org/apache/camel/processor/SagaOptionsTest.java 
b/camel-core/src/test/java/org/apache/camel/processor/SagaOptionsTest.java
index 0551904..7c88f4c 100644
--- a/camel-core/src/test/java/org/apache/camel/processor/SagaOptionsTest.java
+++ b/camel-core/src/test/java/org/apache/camel/processor/SagaOptionsTest.java
@@ -18,14 +18,13 @@ package org.apache.camel.processor;
 
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.apache.camel.impl.saga.InMemorySagaService;
-import org.junit.Assert;
 
 public class SagaOptionsTest extends ContextTestSupport {
 
-
     public void testHeaderForwardedToComplete() throws Exception {
 
         MockEndpoint complete = getMockEndpoint("mock:complete");
@@ -49,7 +48,7 @@ public class SagaOptionsTest extends ContextTestSupport {
 
         try {
             template.sendBodyAndHeader("direct:workflow", "compensate", 
"myname", "Nicola");
-            Assert.fail("Should throw an exception");
+            fail("Should throw an exception");
         } catch (Exception ex) {
             // OK
         }
@@ -57,6 +56,15 @@ public class SagaOptionsTest extends ContextTestSupport {
         compensate.assertIsSatisfied();
     }
 
+    public void testRouteDoesNotHangOnOptionError() throws Exception {
+        try {
+            template.sendBody("direct:wrong-expression", "Hello");
+            fail("Should throw an exception");
+        } catch (RuntimeCamelException ex) {
+            // OK
+        }
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
 
@@ -82,6 +90,11 @@ public class SagaOptionsTest extends ContextTestSupport {
                         .setHeader("name", constant("TryToOverride"))
                         .to("mock:endpoint");
 
+                from("direct:wrong-expression")
+                        .saga()
+                        .option("id", simple("${10 / 0}"))
+                        .to("log:info");
+
             }
         };
     }
diff --git 
a/components/camel-lra/src/main/java/org/apache/camel/service/lra/LRASagaCoordinator.java
 
b/components/camel-lra/src/main/java/org/apache/camel/service/lra/LRASagaCoordinator.java
index 1442454..c870e5e 100644
--- 
a/components/camel-lra/src/main/java/org/apache/camel/service/lra/LRASagaCoordinator.java
+++ 
b/components/camel-lra/src/main/java/org/apache/camel/service/lra/LRASagaCoordinator.java
@@ -40,7 +40,12 @@ public class LRASagaCoordinator implements 
CamelSagaCoordinator {
 
     @Override
     public CompletableFuture<Void> beginStep(Exchange exchange, CamelSagaStep 
step) {
-        LRASagaStep sagaStep = LRASagaStep.fromCamelSagaStep(step, exchange);
+        LRASagaStep sagaStep;
+        try {
+            sagaStep = LRASagaStep.fromCamelSagaStep(step, exchange);
+        } catch (RuntimeException ex) {
+            return CompletableFuture.supplyAsync(() -> {throw ex;});
+        }
         return sagaService.getClient().join(this.lraURL, sagaStep);
     }
 
diff --git 
a/components/camel-lra/src/main/java/org/apache/camel/service/lra/LRASagaStep.java
 
b/components/camel-lra/src/main/java/org/apache/camel/service/lra/LRASagaStep.java
index e4b182d..73a43c1 100644
--- 
a/components/camel-lra/src/main/java/org/apache/camel/service/lra/LRASagaStep.java
+++ 
b/components/camel-lra/src/main/java/org/apache/camel/service/lra/LRASagaStep.java
@@ -23,6 +23,7 @@ import java.util.TreeMap;
 import org.apache.camel.Endpoint;
 import org.apache.camel.Exchange;
 import org.apache.camel.Expression;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.saga.CamelSagaStep;
 
 /**
@@ -48,7 +49,11 @@ public final class LRASagaStep {
         t.timeoutInMilliseconds = step.getTimeoutInMilliseconds();
         t.options = new TreeMap<>();
         for (Map.Entry<String, Expression> entry : 
step.getOptions().entrySet()) {
-            t.options.put(entry.getKey(), entry.getValue().evaluate(exchange, 
String.class));
+            try {
+                t.options.put(entry.getKey(), 
entry.getValue().evaluate(exchange, String.class));
+            } catch (Exception ex) {
+                throw new RuntimeCamelException("Cannot evaluate saga option 
'" + entry.getKey() + "'", ex);
+            }
         }
         return t;
     }
diff --git 
a/components/camel-lra/src/test/java/org/apache/camel/service/lra/LRAOptionsIT.java
 
b/components/camel-lra/src/test/java/org/apache/camel/service/lra/LRAOptionsIT.java
index 72e0a62..f2e4dbf 100644
--- 
a/components/camel-lra/src/test/java/org/apache/camel/service/lra/LRAOptionsIT.java
+++ 
b/components/camel-lra/src/test/java/org/apache/camel/service/lra/LRAOptionsIT.java
@@ -17,6 +17,7 @@
 package org.apache.camel.service.lra;
 
 import org.apache.camel.Exchange;
+import org.apache.camel.RuntimeCamelException;
 import org.apache.camel.builder.RouteBuilder;
 import org.apache.camel.component.mock.MockEndpoint;
 import org.junit.Assert;
@@ -57,6 +58,11 @@ public class LRAOptionsIT extends AbstractLRATestSupport {
         compensate.assertIsSatisfied();
     }
 
+    @Test(expected = RuntimeCamelException.class)
+    public void testRouteDoesNotHangOnOptionError() throws Exception {
+        template.sendBody("direct:wrong-expression", "Hello");
+    }
+
     @Override
     protected RouteBuilder createRouteBuilder() throws Exception {
 
@@ -80,6 +86,11 @@ public class LRAOptionsIT extends AbstractLRATestSupport {
                         .setHeader("name", constant("TryToOverride"))
                         .to("mock:endpoint");
 
+                from("direct:wrong-expression")
+                        .saga()
+                        .option("id", simple("${10 / 0}"))
+                        .to("log:info");
+
             }
         };
     }

-- 
To stop receiving notification emails like this one, please contact
nferr...@apache.org.

Reply via email to