You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by gn...@apache.org on 2026/03/13 07:36:27 UTC

(camel) branch camel-22884-when-method-validation created (now 5d1bc14daa89)

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

gnodet pushed a change to branch camel-22884-when-method-validation
in repository https://gitbox.apache.org/repos/asf/camel.git


      at 5d1bc14daa89 CAMEL-22884: Validate method attribute placement in when clause

This branch includes the following new commits:

     new 5d1bc14daa89 CAMEL-22884: Validate method attribute placement in when clause

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



(camel) 01/01: CAMEL-22884: Validate method attribute placement in when clause

Posted by gn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

gnodet pushed a commit to branch camel-22884-when-method-validation
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 5d1bc14daa89e6a12c59c11c9ced2ce6ced67101
Author: Guillaume Nodet <gn...@gmail.com>
AuthorDate: Fri Mar 13 08:36:13 2026 +0100

    CAMEL-22884: Validate method attribute placement in when clause
    
    Co-Authored-By: Claude Opus 4.6 <no...@anthropic.com>
---
 .../camel/model/BasicOutputExpressionNode.java     | 28 +++++++++++++
 .../org/apache/camel/xml/in/ModelParserTest.java   | 46 ++++++++++++++++++++++
 2 files changed, 74 insertions(+)

diff --git a/core/camel-core-model/src/main/java/org/apache/camel/model/BasicOutputExpressionNode.java b/core/camel-core-model/src/main/java/org/apache/camel/model/BasicOutputExpressionNode.java
index 2ab7ecb72732..469905347bd0 100644
--- a/core/camel-core-model/src/main/java/org/apache/camel/model/BasicOutputExpressionNode.java
+++ b/core/camel-core-model/src/main/java/org/apache/camel/model/BasicOutputExpressionNode.java
@@ -75,4 +75,32 @@ public abstract class BasicOutputExpressionNode extends BasicExpressionNode<Basi
     public void addOutput(ProcessorDefinition<?> output) {
         this.outputs.add(output);
     }
+
+    @Override
+    public void setExpression(ExpressionDefinition expression) {
+        // Detect when an expression element (e.g. <method>) appears after processing steps
+        // inside a when/filter clause in XML/YAML DSL. This is almost certainly a user mistake
+        // where they intended to use <bean> (processor) instead of <method> (expression/predicate).
+        // We skip this check when the existing expression wraps an ExpressionClause (Java DSL),
+        // because preCreateProcessor() legitimately re-sets the expression after resolving it.
+        if (expression != null && getExpression() != null && !outputs.isEmpty()) {
+            ExpressionDefinition existing = getExpression();
+            boolean isExpressionClause
+                    = existing.getExpressionValue() instanceof org.apache.camel.builder.ExpressionClause
+                            || existing.getPredicate() instanceof org.apache.camel.builder.ExpressionClause;
+            if (!isExpressionClause) {
+                String lang = expression.getLanguage() != null
+                        ? expression.getLanguage() : expression.getClass().getSimpleName();
+                throw new IllegalArgumentException(
+                        "The " + getShortName() + " already has a predicate (" + existing
+                                                   + ") and " + outputs.size() + " output(s). "
+                                                   + "The expression '" + lang
+                                                   + "' is being parsed as an expression/predicate but appears after processing steps. "
+                                                   + "If you intended to call a bean method as a processing step, use <bean> instead of <method>. "
+                                                   + "An expression element must be the first child of <" + getShortName()
+                                                   + ">.");
+            }
+        }
+        super.setExpression(expression);
+    }
 }
diff --git a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
index 150e89434e8d..679edbff0924 100644
--- a/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
+++ b/core/camel-xml-io/src/test/java/org/apache/camel/xml/in/ModelParserTest.java
@@ -449,6 +449,52 @@ public class ModelParserTest {
         assertTrue(e.getMessage().startsWith("Unexpected attribute '{}ref'"));
     }
 
+    @Test
+    public void testMethodAfterStepsInWhenClauseShouldFail() throws Exception {
+        String routesXml = "<routes xmlns=\"http://camel.apache.org/schema/xml-io\">"
+                           + "  <route>"
+                           + "    <from uri=\"direct:start\"/>"
+                           + "    <choice>"
+                           + "      <when>"
+                           + "        <simple>${header.foo} == 'bar'</simple>"
+                           + "        <log message=\"Condition met\"/>"
+                           + "        <method ref=\"someBean\" method=\"processFooBar\"/>"
+                           + "      </when>"
+                           + "      <otherwise>"
+                           + "        <to uri=\"mock:other\"/>"
+                           + "      </otherwise>"
+                           + "    </choice>"
+                           + "  </route>"
+                           + "</routes>";
+        Exception e = assertThrows(Exception.class, () -> {
+            new ModelParser(new StringReader(routesXml)).parseRoutesDefinition();
+        });
+        assertTrue(e.getMessage().contains("already has a predicate")
+                || e.getCause().getMessage().contains("already has a predicate"),
+                "Error message should indicate that the when clause already has a predicate: " + e.getMessage());
+    }
+
+    @Test
+    public void testMethodAsPredicateInWhenClauseShouldWork() throws Exception {
+        String routesXml = "<routes xmlns=\"http://camel.apache.org/schema/xml-io\">"
+                           + "  <route>"
+                           + "    <from uri=\"direct:start\"/>"
+                           + "    <choice>"
+                           + "      <when>"
+                           + "        <method ref=\"someBean\" method=\"isFoo\"/>"
+                           + "        <to uri=\"mock:foo\"/>"
+                           + "      </when>"
+                           + "      <otherwise>"
+                           + "        <to uri=\"mock:other\"/>"
+                           + "      </otherwise>"
+                           + "    </choice>"
+                           + "  </route>"
+                           + "</routes>";
+        RoutesDefinition routes = new ModelParser(new StringReader(routesXml)).parseRoutesDefinition().orElse(null);
+        assertNotNull(routes);
+        assertEquals(1, routes.getRoutes().size());
+    }
+
     private Path getResourceFolder() {
         final URL resource = getClass().getClassLoader().getResource("barInterceptorRoute.xml");
         assert resource != null : "Cannot find barInterceptorRoute.xml";