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

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


The following commit(s) were added to refs/heads/main by this push:
     new 92f799e  CAMEL-16534: camel-core - Multiple doTry ..doCatch in Java 
DSL - issue setting outer doCatch blocks
92f799e is described below

commit 92f799ec62f1b3d375ae488f6ea1d2ad14c315ff
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Wed Apr 21 08:59:33 2021 +0200

    CAMEL-16534: camel-core - Multiple doTry ..doCatch in Java DSL - issue 
setting outer doCatch blocks
---
 .../apache/camel/model/ProcessorDefinition.java    |  4 +-
 .../java/org/apache/camel/model/TryDefinition.java | 12 ++++
 .../TwoDoTryAndThrowInInnerCatchIssueTest.java     | 60 ++++++++++--------
 .../modules/ROOT/pages/try-catch-finally.adoc      | 72 +++++++++++++++++++++-
 4 files changed, 120 insertions(+), 28 deletions(-)

diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
 
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
index 0743a44..0cfe946 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/ProcessorDefinition.java
@@ -1112,7 +1112,9 @@ public abstract class ProcessorDefinition<Type extends 
ProcessorDefinition<Type>
 
         // are we already a try?
         if (def instanceof TryDefinition) {
-            return (TryDefinition) def;
+            // then we need special logic to end
+            TryDefinition td = (TryDefinition) def;
+            return (TryDefinition) td.onEndDoTry();
         }
 
         // okay end this and get back to the try
diff --git 
a/core/camel-core-model/src/main/java/org/apache/camel/model/TryDefinition.java 
b/core/camel-core-model/src/main/java/org/apache/camel/model/TryDefinition.java
index 069769c..97bf952 100644
--- 
a/core/camel-core-model/src/main/java/org/apache/camel/model/TryDefinition.java
+++ 
b/core/camel-core-model/src/main/java/org/apache/camel/model/TryDefinition.java
@@ -49,6 +49,8 @@ public class TryDefinition extends 
OutputDefinition<TryDefinition> {
     private boolean initialized;
     @XmlTransient
     private List<ProcessorDefinition<?>> outputsWithoutCatches;
+    @XmlTransient
+    protected int endCounter;
 
     public TryDefinition() {
     }
@@ -185,9 +187,19 @@ public class TryDefinition extends 
OutputDefinition<TryDefinition> {
     @Override
     public void addOutput(ProcessorDefinition<?> output) {
         initialized = false;
+        endCounter = 0;
         super.addOutput(output);
     }
 
+    protected ProcessorDefinition<?> onEndDoTry() {
+        if (endCounter > 0) {
+            return end();
+        } else {
+            endCounter++;
+        }
+        return this;
+    }
+
     @Override
     public void preCreateProcessor() {
         // force re-creating initialization to ensure its up-to-date
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/issues/TwoDoTryAndThrowInInnerCatchIssueTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/issues/TwoDoTryAndThrowInInnerCatchIssueTest.java
index 869525f..26c1363 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/issues/TwoDoTryAndThrowInInnerCatchIssueTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/issues/TwoDoTryAndThrowInInnerCatchIssueTest.java
@@ -16,11 +16,12 @@
  */
 package org.apache.camel.issues;
 
+import java.io.IOException;
+import java.net.MalformedURLException;
+
 import org.apache.camel.ContextTestSupport;
 import org.apache.camel.ExtendedCamelContext;
-import org.apache.camel.LoggingLevel;
 import org.apache.camel.builder.RouteBuilder;
-import org.apache.camel.model.TryDefinition;
 import org.junit.jupiter.api.Test;
 
 import static org.junit.jupiter.api.Assertions.fail;
@@ -35,12 +36,21 @@ public class TwoDoTryAndThrowInInnerCatchIssueTest extends 
ContextTestSupport {
         ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
         String xml = ecc.getModelToXMLDumper().dumpModelAsXml(context, 
context.getRouteDefinition("myroute"));
         log.info(xml);
+        System.out.println(xml);
+
+        getMockEndpoint("mock:catch1").expectedMessageCount(0);
+        getMockEndpoint("mock:catch2").expectedMessageCount(0);
+        getMockEndpoint("mock:catch3").expectedMessageCount(0);
+        getMockEndpoint("mock:catch4").expectedMessageCount(1);
+        getMockEndpoint("mock:catch5").expectedMessageCount(1);
 
         try {
             template.requestBody("direct:test", "test", String.class);
         } catch (Exception e) {
             fail("Should not fail");
         }
+
+        assertMockEndpointsSatisfied();
     }
 
     @Override
@@ -50,36 +60,34 @@ public class TwoDoTryAndThrowInInnerCatchIssueTest extends 
ContextTestSupport {
             public void configure() throws Exception {
                 errorHandler(noErrorHandler());
 
-                TryDefinition try1 = 
from("direct:test").routeId("myroute").doTry();
-
-                TryDefinition try2 = try1.doTry();
-
-                try2.throwException(new IllegalArgumentException("Forced by 
me"))
-                        .doCatch(Exception.class)
-                        .log(LoggingLevel.INFO, 
TwoDoTryAndThrowInInnerCatchIssueTest.class.getName(), "docatch 1")
-                        .throwException(new IllegalArgumentException("Second 
forced by me"))
-                        .end();
-
-                try1.doCatch(Exception.class)
-                        .log(LoggingLevel.INFO, 
TwoDoTryAndThrowInInnerCatchIssueTest.class.getName(), "docatch 3")
-                        .end();
-
-                // stacked doTry in Java DSL has a flaw so you can do as above
-                /*
-                from("direct:test").
-                    doTry().
+                from("direct:test").routeId("myroute")
+                    .doTry().
                         doTry().
                             throwException(new 
IllegalArgumentException("Forced by me"))
+                        .doCatch(IOException.class)
+                            .to("mock:catch1")
+                            .log("docatch 1")
+                            // end this doCatch block
+                            .endDoTry()
+                        .doCatch(NullPointerException.class)
+                            .to("mock:catch2")
+                            .log("docatch 2")
+                            // no end this catch block as Camel can fix this 
itself
+                        .doCatch(MalformedURLException.class)
+                            .to("mock:catch3")
+                            .log("docatch 3")
+                            // end this doCatch block
+                            .endDoTry()
                         .doCatch(Exception.class)
-                            
.log(LoggingLevel.INFO,DoThrowInCatchIssueTest.class.getName(), "docatch 1")
+                            .to("mock:catch4")
+                            .log("docatch 4")
                             .throwException(new 
IllegalArgumentException("Second forced by me"))
-                        .endDoTry() // end catch block
-                    .endDoTry() // end inner try
+                            .endDoTry() // end catch block
+                        .endDoTry() // end inner doTry block
                     .doCatch(Exception.class)
-                        
.log(LoggingLevel.INFO,DoThrowInCatchIssueTest.class.getName(), "docatch 3")
+                        .to("mock:catch5")
+                        .log("docatch 5")
                     .end();
-                            }
-                        };*/
             }
         };
     }
diff --git a/docs/user-manual/modules/ROOT/pages/try-catch-finally.adoc 
b/docs/user-manual/modules/ROOT/pages/try-catch-finally.adoc
index 385b4cc..7b4cda7 100644
--- a/docs/user-manual/modules/ROOT/pages/try-catch-finally.adoc
+++ b/docs/user-manual/modules/ROOT/pages/try-catch-finally.adoc
@@ -74,8 +74,78 @@ the `end()` should be at the end of the finally block. If we 
are not
 using a finally, then the `end()` should be at the end of the `doCatch`
 to indicate the end there.
 
+TIP: Instead of `end()` you can use `endDoTry()` to end and return back to try 
.. catch scope.
+
+=== Using nested doTry .. doCatch EIPs
+
+When nesting doTry .. doCatch from an outer doTry .. doCatch EIP, then pay 
extra attention
+when using Java DSL as the Java programming language is not _indent aware_ so 
you may write
+Java code that are indented in a way where you think that a catch block is 
associated with
+the other doTry but it is not.
+
+Given the following Java DSL:
+
+[source,java]
+----
+from("direct:test").routeId("myroute")
+    .doTry().
+        doTry().
+            throwException(new IllegalArgumentException("Forced by me"))
+        .doCatch(Exception.class)
+            .log("docatch 1")
+            .throwException(new IllegalArgumentException("Second forced by 
me"))
+    .doCatch(Exception.class)
+        .log("docatch 2")
+    .end();
+----
+
+Then you may think that _docatch2_ is associated on the outer doTry because of 
how the code is formatted.
+But it is **not**, both __docatch1__ and __docatch2__ are in the inner doTry, 
and the outer doTry has no catch blocks.
+
+So in this example the route will throw the 1st exception which is then 
handled in __docatch1__ which
+then throw a 2nd exception, that is not caught.
+
+So what you must do is to end the doCatch block correct (notice how we use 
`doEndTry()` two times) as shown below:
+
+[source,java]
+----
+from("direct:test").routeId("myroute")
+    .doTry().
+        doTry().
+            throwException(new IllegalArgumentException("Forced by me"))
+        .doCatch(Exception.class)
+            .log("docatch 1")
+            .throwException(new IllegalArgumentException("Second forced by 
me"))
+         .endDoTry() // end this doCatch block
+     .endDoTry() // end the inner doTry
+    .doCatch(Exception.class)
+        .log("docatch 2")
+    .end();
+----
+
+And by using the `doEndTry()` we can end the block correctly, and an XML 
representation of the route would be as follows:
+[source,xml]
+----
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<route xmlns="http://camel.apache.org/schema/spring";>
+    <from uri="direct:test"/>
+    <doTry>
+        <doTry>
+            <throwException id="throwException1"/>
+            <doCatch id="doCatch1">
+                <log id="log1" message="docatch 1"/>
+                <throwException id="throwException2"/>
+            </doCatch>
+        </doTry>
+        <doCatch id="doCatch2">
+            <log id="log2" message="docatch 2"/>
+        </doCatch>
+    </doTry>
+</route>
+----
+
 [[TryCatchFinally-Usingtry..catch..finallyinSpringDSL]]
-== Using try .. catch .. finally in Spring DSL
+== Using try .. catch .. finally in XML DSL
 
 In the route below we have all keywords in action. As the code is based
 on a unit test we route using xref:components::mock-component.adoc[Mock].

Reply via email to