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 2025/01/30 16:14:05 UTC

(camel) branch main updated: CAMEL-21687: camel-core - Cannot add onCompletion after transacted in Java DSL (#16994)

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 208d3785ddb CAMEL-21687: camel-core - Cannot add onCompletion after transacted in Java DSL (#16994)
208d3785ddb is described below

commit 208d3785ddb3023190346e8413411e53c1923da6
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Thu Jan 30 17:13:59 2025 +0100

    CAMEL-21687: camel-core - Cannot add onCompletion after transacted in Java DSL (#16994)
---
 .../org/apache/camel/spring/interceptor/AnnotatedRoute.java    | 10 ++++++++--
 .../interceptor/TransactionalClientWithAnnotatedBeanTest.java  |  6 ++++++
 .../main/java/org/apache/camel/model/ProcessorDefinition.java  |  3 ++-
 .../java/org/apache/camel/model/RouteDefinitionHelper.java     |  3 ++-
 4 files changed, 18 insertions(+), 4 deletions(-)

diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/AnnotatedRoute.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/AnnotatedRoute.java
index 76e2f76adcf..5070fd7d439 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/AnnotatedRoute.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/AnnotatedRoute.java
@@ -22,10 +22,16 @@ public class AnnotatedRoute extends RouteBuilder {
 
     @Override
     public void configure() throws Exception {
-        from("direct:okay").transacted().setBody(constant("Tiger in Action")).bean("bookService")
+        from("direct:okay").transacted()
+                .onCompletion().onCompleteOnly().to("mock:ok").end()
+                .onCompletion().onFailureOnly().to("mock:fail").end()
+                .setBody(constant("Tiger in Action")).bean("bookService")
                 .setBody(constant("Elephant in Action")).bean("bookService");
 
-        from("direct:fail").transacted().setBody(constant("Tiger in Action")).bean("bookService")
+        from("direct:fail").transacted()
+                .onCompletion().onCompleteOnly().to("mock:ok").end()
+                .onCompletion().onFailureOnly().to("mock:fail").end()
+                .setBody(constant("Tiger in Action")).bean("bookService")
                 .setBody(constant("Donkey in Action")).bean("bookService");
     }
 
diff --git a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithAnnotatedBeanTest.java b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithAnnotatedBeanTest.java
index 3afc461c06f..052a8b9906c 100644
--- a/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithAnnotatedBeanTest.java
+++ b/components/camel-spring-xml/src/test/java/org/apache/camel/spring/interceptor/TransactionalClientWithAnnotatedBeanTest.java
@@ -27,6 +27,9 @@ public class TransactionalClientWithAnnotatedBeanTest extends TransactionalClien
     @Override
     @Test
     public void testTransactionSuccess() throws Exception {
+        getMockEndpoint("mock:ok").expectedMessageCount(1);
+        getMockEndpoint("mock:fail").expectedMessageCount(0);
+
         MockEndpoint book = getMockEndpoint("mock:book");
         book.expectedMessageCount(2);
 
@@ -38,6 +41,9 @@ public class TransactionalClientWithAnnotatedBeanTest extends TransactionalClien
     @Override
     @Test
     public void testTransactionRollback() throws Exception {
+        getMockEndpoint("mock:ok").expectedMessageCount(0);
+        getMockEndpoint("mock:fail").expectedMessageCount(1);
+
         MockEndpoint book = getMockEndpoint("mock:book");
         book.expectedMessageCount(1);
 
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 eb9c0cf2c41..b848914af37 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
@@ -213,7 +213,8 @@ public abstract class ProcessorDefinition<Type extends ProcessorDefinition<Type>
         // still allow if using advice-with)
         boolean parentIsRoute = RouteDefinition.class.isAssignableFrom(this.getClass())
                 || AdviceWithDefinition.class.isAssignableFrom(this.getClass());
-        if (output.isTopLevelOnly() && !parentIsRoute) {
+        boolean parentIsAlreadyTop = this.isTopLevelOnly();
+        if (output.isTopLevelOnly() && !parentIsRoute && !parentIsAlreadyTop) {
             throw new IllegalArgumentException(
                     "The output must be added as top-level on the route. Try moving " + output + " to the top of route.");
         }
diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
index e416aa4eeed..da1748462db 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/RouteDefinitionHelper.java
@@ -459,7 +459,8 @@ public final class RouteDefinitionHelper {
             // validate that top-level is only added on the route (eg top level)
             RouteDefinition route = ProcessorDefinitionHelper.getRoute(child);
             boolean parentIsRoute = child.getParent() == route;
-            if (child.isTopLevelOnly() && !parentIsRoute) {
+            boolean parentIsAlreadyTop = child.getParent() == null || child.getParent().isTopLevelOnly();
+            if (child.isTopLevelOnly() && !(parentIsRoute || parentIsAlreadyTop)) {
                 throw new IllegalArgumentException(
                         "The output must be added as top-level on the route. Try moving " + child + " to the top of route.");
             }