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 a8ad07ae0286 CAMEL-25033: camel-bean - pass a parameter value from
${body} or ${header.x} in the method name as-is (#26908)
a8ad07ae0286 is described below
commit a8ad07ae0286c9f3d3fa02b0616138f841f94e39
Author: allthingssecurity <[email protected]>
AuthorDate: Mon Sep 28 13:32:42 2026 +0530
CAMEL-25033: camel-bean - pass a parameter value from ${body} or
${header.x} in the method name as-is (#26908)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../apache/camel/component/bean/MethodInfo.java | 20 ++--
.../bean/BeanParameterValueFromExpressionTest.java | 107 +++++++++++++++++++++
.../modules/ROOT/pages/bean-binding.adoc | 5 +
.../ROOT/pages/camel-4x-upgrade-guide-4_23.adoc | 11 +++
4 files changed, 137 insertions(+), 6 deletions(-)
diff --git
a/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
b/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
index a3aac1320046..4f5e31a6731c 100644
---
a/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
+++
b/components/camel-bean/src/main/java/org/apache/camel/component/bean/MethodInfo.java
@@ -723,12 +723,24 @@ public class MethodInfo {
return null;
}
+ // an explicit null parameter value
+ if ("null".equals(exp)) {
+ return Void.TYPE;
+ }
+
parameterValue = evaluateSimpleExpression(exchange, index, exp);
- if ("null".equals(parameterValue)) {
+ // the expression evaluated to null, which is a valid value we
need to honor
+ if (parameterValue == null) {
return Void.TYPE;
}
+ // we need to unquote a quoted String parameter value, as the
enclosing quotes is there to denote a
+ // parameter value, but a value from an expression such as ${body}
or ${header.foo} is used as-is
+ if (StringHelper.isQuoted(exp.trim()) && parameterValue instanceof
String string) {
+ parameterValue =
StringHelper.removeLeadingAndEndingQuotes(string);
+ }
+
boolean valid = isValidParameterValue(exchange, exp,
parameterValue, parameterType, varargs);
if (!valid) {
return null;
@@ -760,8 +772,7 @@ public class MethodInfo {
Expression expression = null;
try {
expression =
exchange.getContext().resolveLanguage("simple").createExpression(exp);
- Object result = expression.evaluate(exchange, Object.class);
- return result != null ? result : "null";
+ return expression.evaluate(exchange, Object.class);
} catch (Exception e) {
throw new ExpressionEvaluationException(
expression, "Cannot create/evaluate simple expression:
" + exp
@@ -788,9 +799,6 @@ public class MethodInfo {
private Object convertParameterValue(
Exchange exchange, int index, Object parameterValue, Class<?>
parameterType, boolean varargs) {
- if (parameterValue instanceof String string) {
- parameterValue =
StringHelper.removeLeadingAndEndingQuotes(string);
- }
if (varargs) {
return parameterValue;
}
diff --git
a/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterValueFromExpressionTest.java
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterValueFromExpressionTest.java
new file mode 100644
index 000000000000..6bfd9a498b7e
--- /dev/null
+++
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterValueFromExpressionTest.java
@@ -0,0 +1,107 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.bean;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spi.Registry;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+/**
+ * A parameter value in the method name that is a Simple expression, such as
${body} or ${header.foo}, is passed to the
+ * method as-is. Only the quotes of a quoted literal are removed, and only the
literal null is a null value.
+ */
+class BeanParameterValueFromExpressionTest extends ContextTestSupport {
+
+ private final MyBean bean = new MyBean();
+
+ @Test
+ void testQuotedHeaderValue() {
+ assertEquals("[\"33a64df5\"]",
template.requestBodyAndHeader("direct:header", "Hello", "v", "\"33a64df5\""));
+ assertEquals("['abc']", template.requestBodyAndHeader("direct:header",
"Hello", "v", "'abc'"));
+ assertEquals("[ 'x' ]",
template.requestBodyAndHeader("direct:header", "Hello", "v", " 'x' "));
+ assertEquals("['abc']",
template.requestBodyAndHeader("direct:headerUri", "Hello", "v", "'abc'"));
+ }
+
+ @Test
+ void testQuotedBody() {
+ assertEquals("[\"ACME, Inc.\",\"42\"]",
template.requestBody("direct:body", "\"ACME, Inc.\",\"42\""));
+ assertEquals("['']", template.requestBody("direct:body", "''"));
+ }
+
+ @Test
+ void testQuotedHeaderValues() {
+ assertEquals("['x'|\"y\"]", template.requestBody("direct:two",
"Hello"));
+ }
+
+ @Test
+ void testNullText() {
+ // the text null is not the null keyword
+ assertEquals("[null]", template.requestBodyAndHeader("direct:header",
"Hello", "v", "null"));
+ // but an expression that evaluates to null is still passed as null
+ assertEquals("<null>", template.requestBody("direct:header", "Hello"));
+ }
+
+ @Test
+ void testLiterals() {
+ assertEquals("[abc]", template.requestBodyAndHeader("direct:header",
"Hello", "v", "abc"));
+ assertEquals("[World]", template.requestBody("direct:single",
"Hello"));
+ assertEquals("[World]", template.requestBody("direct:double",
"Hello"));
+ assertEquals("<null>", template.requestBody("direct:null", "Hello"));
+ assertEquals("[null]", template.requestBody("direct:quotedNull",
"Hello"));
+ assertEquals("[\"abc\"]",
template.requestBodyAndHeader("direct:quotedHeader", "Hello", "v", "\"abc\""));
+ }
+
+ @Override
+ protected Registry createCamelRegistry() throws Exception {
+ Registry jndi = super.createCamelRegistry();
+ jndi.bind("foo", new MyBean());
+ return jndi;
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("direct:header").bean(bean, "echo(${header.v})");
+
from("direct:headerUri").to("bean:foo?method=echo(${header.v})");
+ from("direct:body").bean(bean, "echo(${body})");
+ from("direct:two").setHeader("a",
constant("'x'")).setHeader("b", constant("\"y\""))
+ .bean(bean, "two(${header.a}, ${header.b})");
+ from("direct:single").bean(bean, "echo('World')");
+ from("direct:double").bean(bean, "echo(\"World\")");
+ from("direct:null").bean(bean, "echo(null)");
+ from("direct:quotedNull").bean(bean, "echo('null')");
+ from("direct:quotedHeader").bean(bean, "echo('${header.v}')");
+ }
+ };
+ }
+
+ public static class MyBean {
+
+ public String echo(String s) {
+ return s == null ? "<null>" : "[" + s + "]";
+ }
+
+ public String two(String a, String b) {
+ return "[" + a + "|" + b + "]";
+ }
+ }
+}
diff --git a/docs/user-manual/modules/ROOT/pages/bean-binding.adoc
b/docs/user-manual/modules/ROOT/pages/bean-binding.adoc
index 1c1c93e83cf1..b69720872de3 100644
--- a/docs/user-manual/modules/ROOT/pages/bean-binding.adoc
+++ b/docs/user-manual/modules/ROOT/pages/bean-binding.adoc
@@ -277,6 +277,11 @@ The syntax of the parameters is using the
xref:components:languages:simple-langu
language so we have to use `${ }` placeholders in the body to
refer to the message body.
+The value of a Simple expression such as `$\{body}` or `${header.foo}` is
passed to the method as-is.
+Quotes in the value are kept, and a value that is the text `null` is passed as
that text.
+Only a parameter written as a quoted String, such as `'World'`, has its quotes
removed,
+and only the parameter `null` (without quotes) is a `null` value.
+
If you want to pass in a `null` value, then you can explicitly define this
in the method option as shown below:
diff --git
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
index 7f8a3c26da79..50a590a0a90b 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_23.adoc
@@ -985,6 +985,17 @@ an `AGENTS.md` file with guidance for AI coding
assistants, pointing at the Apac
The `camel-archetype-api-component` archetype also generates its readme again:
the file was declared
in the wrong file set and was therefore silently skipped.
+=== camel-bean - parameter values in the method name
+
+A parameter value in the method name that is a Simple expression, such as
`+bean(MyBean.class, "process(${body})")+`
+or `+to("bean:foo?method=check(${header.ETag})")+`, is now passed to the
method as-is. Previously, when the value was a
+String that started and ended with the same quote (single or double), the
quotes were removed, and a value that was the
+text `null` was passed as a Java `null`. For example the `ETag` value
`"33a64df5"` was passed as `33a64df5`.
+
+Quoted String parameters such as `process('World')` still have their quotes
removed, and the parameter `null` still
+passes `null`, as before. An expression that evaluates to `null` also still
passes `null`. If a method relied on the old
+behavior for a value from an expression, then it must remove the quotes, or
check for the text `null`, itself.
+
=== camel-debezium-oracle (breaking change)
The parameters `logMiningBufferEhcacheRollbacksConfig`,
`logMiningBufferInfinispanCacheRollbacks` have been removed due to the upgrade
of Debezium to 3.6.3.Final.