You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2026/07/22 11:22:49 UTC
(camel) 04/08: CAMEL-24237: Add doTry EIP documentation and skip when/otherwise from EIP list
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch feature/CAMEL-24237-catalog-docs
in repository https://gitbox.apache.org/repos/asf/camel.git
commit 9ff8d69c0e37a20f4a5a5e12c2ccf1fa66e40c8a
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Jul 22 13:07:14 2026 +0200
CAMEL-24237: Add doTry EIP documentation and skip when/otherwise from EIP list
Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
Signed-off-by: Claus Ibsen <cl...@gmail.com>
---
.../org/apache/camel/catalog/docs.properties | 1 +
.../org/apache/camel/catalog/docs/doTry-eip.adoc | 246 +++++++++++++++++++++
.../main/docs/modules/eips/pages/doTry-eip.adoc | 246 +++++++++++++++++++++
.../dsl/jbang/core/commands/tui/CatalogTab.java | 4 +
4 files changed, 497 insertions(+)
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties
index 518dd4f70586..8b971e97b717 100644
--- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs.properties
@@ -152,6 +152,7 @@ disruptor-component
disruptor-vm-component
djl-component
dns-component
+doTry-eip
docker-component
docling-async-processing
docling-batch-processing
diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/doTry-eip.adoc b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/doTry-eip.adoc
new file mode 100644
index 000000000000..0b43a808862f
--- /dev/null
+++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/docs/doTry-eip.adoc
@@ -0,0 +1,246 @@
+= Do Try EIP
+:doctitle: Do Try
+:shortname: doTry
+:description: Wraps route steps in a try-catch-finally block for fine-grained exception handling within the route
+:since:
+:supportlevel: Stable
+:tabs-sync-option:
+
+Camel supports the Java equivalent of try, catch, and finally directly in the DSL.
+It aims to work like its Java sisters but with more power.
+
+In Camel, we prefix the keywords with `do` to avoid having same keyword as Java.
+So we have:
+
+- `doTry`
+- `doCatch`
+- `doFinally`
+- `end` to end the block in Java DSL
+
+[IMPORTANT]
+====
+When using `doTry ... doCatch ... doFinally`, the regular Camel
+xref:manual::error-handler.adoc[Error Handler] is not in use; meaning any
+`onException` or the likes does not trigger.
+
+The reason is that
+`doTry ... doCatch ... doFinally` is in fact its own error handler and mimics how try/catch/finally works in Java.
+====
+
+== EIP options
+
+// eip options: START
+include::partial$eip-options.adoc[]
+// eip options: END
+
+== Using doTry ... doCatch ... doFinally
+
+In the route below we have all of them in action:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .doTry()
+ .process(new ProcessorFail())
+ .to("mock:result")
+ .doCatch(IOException.class, IllegalStateException.class)
+ .to("mock:catch")
+ .doFinally()
+ .to("mock:finally")
+ .end();
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <doTry>
+ <process ref="processorFail"/>
+ <to uri="mock:result"/>
+ <doCatch>
+ <exception>java.io.IOException</exception>
+ <exception>java.lang.IllegalStateException</exception>
+ <to uri="mock:catch"/>
+ </doCatch>
+ <doFinally>
+ <to uri="mock:finally"/>
+ </doFinally>
+ </doTry>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - doTry:
+ steps:
+ - process:
+ ref: processorFail
+ - to:
+ uri: mock:result
+ - doCatch:
+ exception:
+ - java.io.IOException
+ - java.lang.IllegalStateException
+ steps:
+ - to:
+ uri: mock:catch
+ - doFinally:
+ steps:
+ - to:
+ uri: mock:finally
+----
+====
+
+=== Using onWhen with doCatch
+
+You can use xref:manual::predicate.adoc[Predicates] with `doCatch` to make it determine at runtime if the block should be triggered or not.
+In this example, we only want to trigger if the caused exception message contains the word *Damn*.
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .doTry()
+ .process(new ProcessorFail())
+ .to("mock:result")
+ .doCatch(IOException.class, IllegalStateException.class)
+ .onWhen(exceptionMessage().contains("Damn"))
+ .to("mock:catch")
+ .doCatch(CamelExchangeException.class)
+ .to("mock:catchCamel")
+ .doFinally()
+ .to("mock:finally")
+ .end();
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <doTry>
+ <process ref="processorFail"/>
+ <to uri="mock:result"/>
+ <doCatch>
+ <exception>java.io.IOException</exception>
+ <exception>java.lang.IllegalStateException</exception>
+ <onWhen>
+ <simple>${exception.message} contains 'Damn'</simple>
+ </onWhen>
+ <to uri="mock:catch"/>
+ </doCatch>
+ <doCatch>
+ <exception>org.apache.camel.CamelExchangeException</exception>
+ <to uri="mock:catchCamel"/>
+ </doCatch>
+ <doFinally>
+ <to uri="mock:finally"/>
+ </doFinally>
+ </doTry>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - doTry:
+ steps:
+ - process:
+ ref: processorFail
+ - to:
+ uri: mock:result
+ - doCatch:
+ exception:
+ - java.io.IOException
+ - java.lang.IllegalStateException
+ steps:
+ - onWhen:
+ expression:
+ simple:
+ expression: "${exception.message} contains 'Damn'"
+ - to:
+ uri: mock:catch
+ - doCatch:
+ exception:
+ - org.apache.camel.CamelExchangeException
+ steps:
+ - to:
+ uri: mock:catchCamel
+ - doFinally:
+ steps:
+ - to:
+ uri: mock:finally
+----
+====
+
+=== Use end() to end the block
+
+When using Java DSL you must use `end()` to indicate where the try ... catch ... finally block ends.
+If the route has a `doFinally`, then the `end()` should be at the end of the finally block.
+If there is no `doFinally`, then the `end()` should be at the end of the last `doCatch`.
+
+TIP: Instead of `end()` you can use `endDoTry()` to end and _return back_ to the try ... catch scope.
+
+=== Nested doTry ... doCatch
+
+When nesting `doTry ... doCatch` from an outer `doTry ... doCatch` EIP,
+pay extra attention when using Java DSL as the Java programming language is not _indent aware_
+so you may write code that is indented in a way where you think a catch block is associated with the other doTry, but it is not.
+
+Given the following Java DSL:
+
+[source,java]
+----
+from("direct:test")
+ .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();
+----
+
+Both `docatch 1` and `docatch 2` are in the inner `doTry`, and the outer `doTry` has no catch blocks.
+Use `endDoTry()` to end the blocks correctly:
+
+[source,java]
+----
+from("direct:test")
+ .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();
+----
diff --git a/core/camel-core-engine/src/main/docs/modules/eips/pages/doTry-eip.adoc b/core/camel-core-engine/src/main/docs/modules/eips/pages/doTry-eip.adoc
new file mode 100644
index 000000000000..0b43a808862f
--- /dev/null
+++ b/core/camel-core-engine/src/main/docs/modules/eips/pages/doTry-eip.adoc
@@ -0,0 +1,246 @@
+= Do Try EIP
+:doctitle: Do Try
+:shortname: doTry
+:description: Wraps route steps in a try-catch-finally block for fine-grained exception handling within the route
+:since:
+:supportlevel: Stable
+:tabs-sync-option:
+
+Camel supports the Java equivalent of try, catch, and finally directly in the DSL.
+It aims to work like its Java sisters but with more power.
+
+In Camel, we prefix the keywords with `do` to avoid having same keyword as Java.
+So we have:
+
+- `doTry`
+- `doCatch`
+- `doFinally`
+- `end` to end the block in Java DSL
+
+[IMPORTANT]
+====
+When using `doTry ... doCatch ... doFinally`, the regular Camel
+xref:manual::error-handler.adoc[Error Handler] is not in use; meaning any
+`onException` or the likes does not trigger.
+
+The reason is that
+`doTry ... doCatch ... doFinally` is in fact its own error handler and mimics how try/catch/finally works in Java.
+====
+
+== EIP options
+
+// eip options: START
+include::partial$eip-options.adoc[]
+// eip options: END
+
+== Using doTry ... doCatch ... doFinally
+
+In the route below we have all of them in action:
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .doTry()
+ .process(new ProcessorFail())
+ .to("mock:result")
+ .doCatch(IOException.class, IllegalStateException.class)
+ .to("mock:catch")
+ .doFinally()
+ .to("mock:finally")
+ .end();
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <doTry>
+ <process ref="processorFail"/>
+ <to uri="mock:result"/>
+ <doCatch>
+ <exception>java.io.IOException</exception>
+ <exception>java.lang.IllegalStateException</exception>
+ <to uri="mock:catch"/>
+ </doCatch>
+ <doFinally>
+ <to uri="mock:finally"/>
+ </doFinally>
+ </doTry>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - doTry:
+ steps:
+ - process:
+ ref: processorFail
+ - to:
+ uri: mock:result
+ - doCatch:
+ exception:
+ - java.io.IOException
+ - java.lang.IllegalStateException
+ steps:
+ - to:
+ uri: mock:catch
+ - doFinally:
+ steps:
+ - to:
+ uri: mock:finally
+----
+====
+
+=== Using onWhen with doCatch
+
+You can use xref:manual::predicate.adoc[Predicates] with `doCatch` to make it determine at runtime if the block should be triggered or not.
+In this example, we only want to trigger if the caused exception message contains the word *Damn*.
+
+[tabs]
+====
+
+Java::
++
+[source,java]
+----
+from("direct:start")
+ .doTry()
+ .process(new ProcessorFail())
+ .to("mock:result")
+ .doCatch(IOException.class, IllegalStateException.class)
+ .onWhen(exceptionMessage().contains("Damn"))
+ .to("mock:catch")
+ .doCatch(CamelExchangeException.class)
+ .to("mock:catchCamel")
+ .doFinally()
+ .to("mock:finally")
+ .end();
+----
+
+XML::
++
+[source,xml]
+----
+<route>
+ <from uri="direct:start"/>
+ <doTry>
+ <process ref="processorFail"/>
+ <to uri="mock:result"/>
+ <doCatch>
+ <exception>java.io.IOException</exception>
+ <exception>java.lang.IllegalStateException</exception>
+ <onWhen>
+ <simple>${exception.message} contains 'Damn'</simple>
+ </onWhen>
+ <to uri="mock:catch"/>
+ </doCatch>
+ <doCatch>
+ <exception>org.apache.camel.CamelExchangeException</exception>
+ <to uri="mock:catchCamel"/>
+ </doCatch>
+ <doFinally>
+ <to uri="mock:finally"/>
+ </doFinally>
+ </doTry>
+</route>
+----
+
+YAML::
++
+[source,yaml]
+----
+- route:
+ from:
+ uri: direct:start
+ steps:
+ - doTry:
+ steps:
+ - process:
+ ref: processorFail
+ - to:
+ uri: mock:result
+ - doCatch:
+ exception:
+ - java.io.IOException
+ - java.lang.IllegalStateException
+ steps:
+ - onWhen:
+ expression:
+ simple:
+ expression: "${exception.message} contains 'Damn'"
+ - to:
+ uri: mock:catch
+ - doCatch:
+ exception:
+ - org.apache.camel.CamelExchangeException
+ steps:
+ - to:
+ uri: mock:catchCamel
+ - doFinally:
+ steps:
+ - to:
+ uri: mock:finally
+----
+====
+
+=== Use end() to end the block
+
+When using Java DSL you must use `end()` to indicate where the try ... catch ... finally block ends.
+If the route has a `doFinally`, then the `end()` should be at the end of the finally block.
+If there is no `doFinally`, then the `end()` should be at the end of the last `doCatch`.
+
+TIP: Instead of `end()` you can use `endDoTry()` to end and _return back_ to the try ... catch scope.
+
+=== Nested doTry ... doCatch
+
+When nesting `doTry ... doCatch` from an outer `doTry ... doCatch` EIP,
+pay extra attention when using Java DSL as the Java programming language is not _indent aware_
+so you may write code that is indented in a way where you think a catch block is associated with the other doTry, but it is not.
+
+Given the following Java DSL:
+
+[source,java]
+----
+from("direct:test")
+ .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();
+----
+
+Both `docatch 1` and `docatch 2` are in the inner `doTry`, and the outer `doTry` has no catch blocks.
+Use `endDoTry()` to end the blocks correctly:
+
+[source,java]
+----
+from("direct:test")
+ .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();
+----
diff --git a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CatalogTab.java b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CatalogTab.java
index 65852839d7bd..113b4a8d269a 100644
--- a/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CatalogTab.java
+++ b/dsl/camel-jbang/camel-jbang-plugin-tui/src/main/java/org/apache/camel/dsl/jbang/core/commands/tui/CatalogTab.java
@@ -578,7 +578,11 @@ class CatalogTab extends AbstractTableTab {
}
}
+ Set<String> skipEips = Set.of("when", "otherwise");
for (String name : eipNames) {
+ if (skipEips.contains(name)) {
+ continue;
+ }
EipModel model = catalog.eipModel(name);
if (model == null) {
continue;