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 62f3378470c CAMEL-21817: camel-bean: add support for invoking methods 
with vararg… (#17318)
62f3378470c is described below

commit 62f3378470cfd47b6041b02c54234e646f8b835a
Author: Claus Ibsen <claus.ib...@gmail.com>
AuthorDate: Sat Mar 1 11:28:22 2025 +0000

    CAMEL-21817: camel-bean: add support for invoking methods with vararg… 
(#17318)
    
    * CAMEL-21817: camel-bean: add support for invoking methods with vararg 
parameters
---
 .../org/apache/camel/component/bean/BeanInfo.java  |   9 +-
 .../apache/camel/component/bean/MethodInfo.java    | 139 ++++++++++++++-------
 .../apache/camel/component/bean/ParameterInfo.java |   9 +-
 .../component/bean/BeanParameterInfoTest.java      |   2 +-
 .../component/bean/BeanVarargsInject4Test.java     |  61 +++++++++
 .../component/bean/BeanVarargsInject5Test.java     |  62 +++++++++
 .../component/bean/BeanVarargsInject6Test.java     |  64 ++++++++++
 .../component/bean/BeanVarargsInject7Test.java     |  67 ++++++++++
 8 files changed, 362 insertions(+), 51 deletions(-)

diff --git 
a/components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanInfo.java
 
b/components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanInfo.java
index cc0402c9510..aa8e1d9e0f0 100644
--- 
a/components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanInfo.java
+++ 
b/components/camel-bean/src/main/java/org/apache/camel/component/bean/BeanInfo.java
@@ -286,7 +286,7 @@ public class BeanInfo {
             // and therefore use arrayLength from ObjectHelper to return the 
array length field.
             Method method = 
org.apache.camel.util.ObjectHelper.class.getMethod("arrayLength", 
Object[].class);
             ParameterInfo pi = new ParameterInfo(
-                    0, Object[].class, null, 
ExpressionBuilder.mandatoryBodyExpression(Object[].class, true));
+                    0, Object[].class, false, null, 
ExpressionBuilder.mandatoryBodyExpression(Object[].class, true));
             List<ParameterInfo> lpi = new ArrayList<>(1);
             lpi.add(pi);
             methodInfo = new MethodInfo(exchange.getContext(), 
pojo.getClass(), method, lpi, lpi, false, false);
@@ -447,6 +447,7 @@ public class BeanInfo {
         boolean hasHandlerAnnotation = 
org.apache.camel.util.ObjectHelper.hasAnnotation(method.getAnnotations(), 
Handler.class);
 
         int size = parameterTypes.length;
+
         if (LOG.isTraceEnabled()) {
             LOG.trace("Creating MethodInfo for class: {} method: {} having {} 
parameters", clazz, method, size);
         }
@@ -457,13 +458,15 @@ public class BeanInfo {
                     = parametersAnnotations[i].toArray(new Annotation[0]);
             Expression expression = createParameterUnmarshalExpression(method, 
parameterType, parameterAnnotations);
             hasCustomAnnotation |= expression != null;
+            // whether this parameter is vararg which must be last parameter
+            boolean varargs = method.isVarArgs() && i == size - 1;
 
-            ParameterInfo parameterInfo = new ParameterInfo(i, parameterType, 
parameterAnnotations, expression);
+            ParameterInfo parameterInfo = new ParameterInfo(i, parameterType, 
varargs, parameterAnnotations, expression);
             LOG.trace("Parameter #{}: {}", i, parameterInfo);
             parameters.add(parameterInfo);
             if (expression == null) {
                 boolean bodyAnnotation = 
org.apache.camel.util.ObjectHelper.hasAnnotation(parameterAnnotations, 
Body.class);
-                LOG.trace("Parameter #{} has @Body annotation", i);
+                LOG.trace("Parameter #{} has @Body annotation: {}", i, 
bodyAnnotation);
                 hasCustomAnnotation |= bodyAnnotation;
                 if (bodyParameters.isEmpty()) {
                     // okay we have not yet set the body parameter and we have 
found
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 1d601e5cec6..6b553fcd073 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
@@ -21,6 +21,7 @@ import java.lang.reflect.AccessibleObject;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.lang.reflect.Modifier;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -608,31 +609,36 @@ public class MethodInfo {
          * Evaluates all the parameter expressions
          */
         private Object[] evaluateParameterExpressions(Exchange exchange, 
Object body, Iterator<?> it) {
-            Object[] answer = new Object[expressions.length];
-            for (int i = 0; i < expressions.length; i++) {
-
+            Object[] answer = new Object[expressions != null ? 
expressions.length : 1];
+            for (int i = 0; expressions == null || i < expressions.length; 
i++) {
                 if (body instanceof StreamCache) {
                     // need to reset stream cache for each expression as you 
may access the message body in multiple parameters
                     ((StreamCache) body).reset();
                 }
 
-                // grab the parameter value for the given index
-                Object parameterValue = it != null && it.hasNext() ? it.next() 
: null;
+                // whether its vararg
+                boolean varargs = parameters.get(i).isVarargs();
                 // and the expected parameter type
                 Class<?> parameterType = parameters.get(i).getType();
                 // the value for the parameter to use
                 Object value = null;
 
-                // prefer to use parameter value if given, as they override 
any bean parameter binding
-                // we should skip * as its a type placeholder to indicate any 
type
-                if (parameterValue != null && !parameterValue.equals("*")) {
-                    // evaluate the parameter value binding
-                    value = evaluateParameterValue(exchange, i, 
parameterValue, parameterType);
+                if (varargs) {
+                    value = evaluateVarargsParameterExpressions(exchange, 
body, it);
+                } else {
+                    // grab the parameter value for the given index
+                    Object parameterValue = it != null && it.hasNext() ? 
it.next() : null;
+                    // prefer to use parameter value if given, as they 
override any bean parameter binding
+                    // we should skip * as its a type placeholder to indicate 
any type
+                    if (parameterValue != null && !parameterValue.equals("*")) 
{
+                        // evaluate the parameter value binding
+                        value = evaluateParameterValue(exchange, i, 
parameterValue, parameterType, false);
+                    }
                 }
                 // use bean parameter binding, if still no value
-                Expression expression = expressions[i];
+                Expression expression = expressions != null ? expressions[i] : 
null;
                 if (value == null && expression != null) {
-                    value = evaluateParameterBinding(exchange, expression, i, 
parameterType);
+                    value = evaluateParameterBinding(exchange, expression, i, 
parameterType, false);
                 }
                 // remember the value to use
                 if (value != Void.TYPE) {
@@ -643,6 +649,35 @@ public class MethodInfo {
             return answer;
         }
 
+        /**
+         * Evaluate the remainder parameter as a single vararg
+         */
+        private Object evaluateVarargsParameterExpressions(Exchange exchange, 
Object body, Iterator<?> it) {
+            // special for varargs
+            if (body instanceof StreamCache) {
+                // need to reset stream cache for each expression as you may 
access the message body in multiple parameters
+                ((StreamCache) body).reset();
+            }
+            List<Object> answer = new ArrayList<>();
+            int i = 0;
+            while (it.hasNext()) {
+                Object parameterValue = it.next();
+                Object value = null;
+                // prefer to use parameter value if given, as they override 
any bean parameter binding
+                // we should skip * as its a type placeholder to indicate any 
type
+                if (parameterValue != null && !parameterValue.equals("*")) {
+                    // evaluate the parameter value binding
+                    value = evaluateParameterValue(exchange, i, 
parameterValue, Object.class, true);
+                }
+                // remember the value to use
+                if (value != Void.TYPE) {
+                    answer.add(value);
+                }
+                i++;
+            }
+            return answer.toArray(new Object[0]);
+        }
+
         /**
          * Evaluate using parameter values where the values can be provided in 
the method name syntax.
          * <p/>
@@ -654,7 +689,9 @@ public class MethodInfo {
          * <li>a non <tt>null</tt> value - if the parameter was a parameter 
value, and to be used</li>
          * </ul>
          */
-        private Object evaluateParameterValue(Exchange exchange, int index, 
Object parameterValue, Class<?> parameterType) {
+        private Object evaluateParameterValue(
+                Exchange exchange, int index, Object parameterValue, Class<?> 
parameterType,
+                boolean varargs) {
             Object answer = null;
 
             // convert the parameter value to a String
@@ -669,7 +706,7 @@ public class MethodInfo {
 
                 // check if its a valid parameter value (no type declared via 
.class syntax)
                 valid = BeanHelper.isValidParameterValue(exp);
-                if (!valid) {
+                if (!valid && !varargs) {
                     // it may be a parameter type instead, and if so, then we 
should return null,
                     // as this method is only for evaluating parameter values
                     Boolean isClass = 
BeanHelper.isAssignableToExpectedType(exchange.getContext().getClassResolver(), 
exp,
@@ -703,7 +740,7 @@ public class MethodInfo {
                 }
 
                 // the parameter value may match the expected type, then we 
use it as-is
-                if (parameterType.isAssignableFrom(parameterValue.getClass())) 
{
+                if (varargs || 
parameterType.isAssignableFrom(parameterValue.getClass())) {
                     valid = true;
                 } else {
                     // String values from the simple language is always valid
@@ -724,20 +761,25 @@ public class MethodInfo {
                     if (parameterValue instanceof String) {
                         parameterValue = 
StringHelper.removeLeadingAndEndingQuotes((String) parameterValue);
                     }
-                    try {
-                        // it is a valid parameter value, so convert it to the 
expected type of the parameter
-                        answer = 
exchange.getContext().getTypeConverter().mandatoryConvertTo(parameterType, 
exchange,
-                                parameterValue);
-                        if (LOG.isTraceEnabled()) {
-                            LOG.trace("Parameter #{} evaluated as: {} type: 
{}", index, answer,
-                                    
org.apache.camel.util.ObjectHelper.type(answer));
-                        }
-                    } catch (Exception e) {
-                        if (LOG.isDebugEnabled()) {
-                            LOG.debug("Cannot convert from type: {} to type: 
{} for parameter #{}",
-                                    
org.apache.camel.util.ObjectHelper.type(parameterValue), parameterType, index);
+                    if (varargs) {
+                        // use the value as-is
+                        answer = parameterValue;
+                    } else {
+                        try {
+                            // it is a valid parameter value, so convert it to 
the expected type of the parameter
+                            answer = 
exchange.getContext().getTypeConverter().mandatoryConvertTo(parameterType, 
exchange,
+                                    parameterValue);
+                            if (LOG.isTraceEnabled()) {
+                                LOG.trace("Parameter #{} evaluated as: {} 
type: {}", index, answer,
+                                        
org.apache.camel.util.ObjectHelper.type(answer));
+                            }
+                        } catch (Exception e) {
+                            if (LOG.isDebugEnabled()) {
+                                LOG.debug("Cannot convert from type: {} to 
type: {} for parameter #{}",
+                                        
org.apache.camel.util.ObjectHelper.type(parameterValue), parameterType, index);
+                            }
+                            throw new ParameterBindingException(e, method, 
index, parameterType, parameterValue);
                         }
-                        throw new ParameterBindingException(e, method, index, 
parameterType, parameterValue);
                     }
                 }
             }
@@ -748,30 +790,35 @@ public class MethodInfo {
         /**
          * Evaluate using classic parameter binding using the pre compute 
expression
          */
-        private Object evaluateParameterBinding(Exchange exchange, Expression 
expression, int index, Class<?> parameterType) {
+        private Object evaluateParameterBinding(
+                Exchange exchange, Expression expression, int index, Class<?> 
parameterType, boolean varargs) {
             Object answer = null;
 
             // use object first to avoid type conversion so we know if there 
is a value or not
             Object result = expression.evaluate(exchange, Object.class);
             if (result != null) {
-                try {
-                    if (parameterType.isInstance(result)) {
-                        // optimize if the value is already the same type
-                        answer = result;
-                    } else {
-                        // we got a value now try to convert it to the 
expected type
-                        answer = 
exchange.getContext().getTypeConverter().mandatoryConvertTo(parameterType, 
result);
-                    }
-                    if (LOG.isTraceEnabled()) {
-                        LOG.trace("Parameter #{} evaluated as: {} type: {}", 
index, answer,
-                                
org.apache.camel.util.ObjectHelper.type(answer));
-                    }
-                } catch (NoTypeConversionAvailableException e) {
-                    if (LOG.isDebugEnabled()) {
-                        LOG.debug("Cannot convert from type: {} to type: {} 
for parameter #{}",
-                                
org.apache.camel.util.ObjectHelper.type(result), parameterType, index);
+                if (varargs) {
+                    answer = result;
+                } else {
+                    try {
+                        if (parameterType.isInstance(result)) {
+                            // optimize if the value is already the same type
+                            answer = result;
+                        } else {
+                            // we got a value now try to convert it to the 
expected type
+                            answer = 
exchange.getContext().getTypeConverter().mandatoryConvertTo(parameterType, 
result);
+                        }
+                        if (LOG.isTraceEnabled()) {
+                            LOG.trace("Parameter #{} evaluated as: {} type: 
{}", index, answer,
+                                    
org.apache.camel.util.ObjectHelper.type(answer));
+                        }
+                    } catch (NoTypeConversionAvailableException e) {
+                        if (LOG.isDebugEnabled()) {
+                            LOG.debug("Cannot convert from type: {} to type: 
{} for parameter #{}",
+                                    
org.apache.camel.util.ObjectHelper.type(result), parameterType, index);
+                        }
+                        throw new ParameterBindingException(e, method, index, 
parameterType, result);
                     }
-                    throw new ParameterBindingException(e, method, index, 
parameterType, result);
                 }
             } else {
                 LOG.trace("Parameter #{} evaluated as null", index);
diff --git 
a/components/camel-bean/src/main/java/org/apache/camel/component/bean/ParameterInfo.java
 
b/components/camel-bean/src/main/java/org/apache/camel/component/bean/ParameterInfo.java
index 7a593f4da1d..a3d14f21a85 100644
--- 
a/components/camel-bean/src/main/java/org/apache/camel/component/bean/ParameterInfo.java
+++ 
b/components/camel-bean/src/main/java/org/apache/camel/component/bean/ParameterInfo.java
@@ -28,12 +28,14 @@ final class ParameterInfo {
 
     private final int index;
     private final Class<?> type;
+    private final boolean varargs;
     private final Annotation[] annotations;
     private Expression expression;
 
-    ParameterInfo(int index, Class<?> type, Annotation[] annotations, 
Expression expression) {
+    ParameterInfo(int index, Class<?> type, boolean varargs, Annotation[] 
annotations, Expression expression) {
         this.index = index;
         this.type = type;
+        this.varargs = varargs;
         this.annotations = annotations;
         this.expression = expression;
     }
@@ -54,6 +56,10 @@ final class ParameterInfo {
         return type;
     }
 
+    public boolean isVarargs() {
+        return varargs;
+    }
+
     public void setExpression(Expression expression) {
         this.expression = expression;
     }
@@ -64,6 +70,7 @@ final class ParameterInfo {
         sb.append("ParameterInfo");
         sb.append("[index=").append(index);
         sb.append(", type=").append(type);
+        sb.append(", varargs=").append(varargs);
         sb.append(", annotations=").append(annotations == null ? "null" : 
Arrays.asList(annotations).toString());
         sb.append(", expression=").append(expression);
         sb.append(']');
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterInfoTest.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterInfoTest.java
index c6b1e3b1e44..03373ff0c68 100644
--- 
a/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterInfoTest.java
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanParameterInfoTest.java
@@ -31,7 +31,7 @@ public class BeanParameterInfoTest extends ContextTestSupport 
{
     @Test
     public void testMethodPatternUsingMethodAnnotations() {
         Class<?> foo = Foo.class.getClass();
-        ParameterInfo info = new ParameterInfo(1, foo.getClass(), 
foo.getAnnotations(), null);
+        ParameterInfo info = new ParameterInfo(1, foo.getClass(), false, 
foo.getAnnotations(), null);
 
         assertNotNull(info);
         assertNotNull(info.toString());
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject4Test.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject4Test.java
new file mode 100644
index 00000000000..b4d13dd5100
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject4Test.java
@@ -0,0 +1,61 @@
+/*
+ * 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.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.junit.jupiter.api.Test;
+
+public class BeanVarargsInject4Test extends ContextTestSupport {
+
+    private final MyBean myBean = new MyBean();
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                
from("direct:start").to("bean:myBean?method=doSomething(1,2,3)").to("mock:finish");
+            }
+        };
+    }
+
+    @Test
+    public void testVarargs() throws Exception {
+        MockEndpoint end = getMockEndpoint("mock:finish");
+        end.expectedBodiesReceived("Bye with 3 args");
+
+        sendBody("direct:start", "Camel");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected Registry createCamelRegistry() throws Exception {
+        Registry answer = super.createCamelRegistry();
+        answer.bind("myBean", myBean);
+        return answer;
+    }
+
+    public static class MyBean {
+
+        public String doSomething(Object... args) {
+            return "Bye with " + args.length + " args";
+        }
+    }
+}
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject5Test.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject5Test.java
new file mode 100644
index 00000000000..4cd394fa0c6
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject5Test.java
@@ -0,0 +1,62 @@
+/*
+ * 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.Body;
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.junit.jupiter.api.Test;
+
+public class BeanVarargsInject5Test extends ContextTestSupport {
+
+    private final MyBean myBean = new MyBean();
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                
from("direct:start").to("bean:myBean?method=doSomething(*,1,2,3)").to("mock:finish");
+            }
+        };
+    }
+
+    @Test
+    public void testVarargs() throws Exception {
+        MockEndpoint end = getMockEndpoint("mock:finish");
+        end.expectedBodiesReceived("Bye Camel with 3 args");
+
+        sendBody("direct:start", "Camel");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected Registry createCamelRegistry() throws Exception {
+        Registry answer = super.createCamelRegistry();
+        answer.bind("myBean", myBean);
+        return answer;
+    }
+
+    public static class MyBean {
+
+        public String doSomething(@Body String body, Object... args) {
+            return "Bye " + body + " with " + args.length + " args";
+        }
+    }
+}
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject6Test.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject6Test.java
new file mode 100644
index 00000000000..632cb56e144
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject6Test.java
@@ -0,0 +1,64 @@
+/*
+ * 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.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.junit.jupiter.api.Test;
+
+public class BeanVarargsInject6Test extends ContextTestSupport {
+
+    private final MyBean myBean = new MyBean();
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                
from("direct:start").to("bean:myBean?method=doSomething(${body},1,2,3)").to("mock:finish");
+            }
+        };
+    }
+
+    @Test
+    public void testVarargs() throws Exception {
+        MockEndpoint end = getMockEndpoint("mock:finish");
+        end.expectedBodiesReceived("Bye Camel with 3 args (sum=6)");
+
+        sendBody("direct:start", "Camel");
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected Registry createCamelRegistry() throws Exception {
+        Registry answer = super.createCamelRegistry();
+        answer.bind("myBean", myBean);
+        return answer;
+    }
+
+    public static class MyBean {
+
+        public String doSomething(String body, Object... args) {
+            int sum = Integer.parseInt((String) args[0]);
+            sum += Integer.parseInt((String) args[1]);
+            sum += Integer.parseInt((String) args[2]);
+            return "Bye " + body + " with " + args.length + " args (sum=" + 
sum + ")";
+        }
+    }
+}
diff --git 
a/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject7Test.java
 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject7Test.java
new file mode 100644
index 00000000000..dae818a7950
--- /dev/null
+++ 
b/core/camel-core/src/test/java/org/apache/camel/component/bean/BeanVarargsInject7Test.java
@@ -0,0 +1,67 @@
+/*
+ * 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 java.util.Map;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.spi.Registry;
+import org.junit.jupiter.api.Test;
+
+public class BeanVarargsInject7Test extends ContextTestSupport {
+
+    private final MyBean myBean = new MyBean();
+
+    @Override
+    protected RouteBuilder createRouteBuilder() {
+        return new RouteBuilder() {
+            public void configure() {
+                
from("direct:start").to("bean:myBean?method=doSomething(${header.myArr},1,2,3)").to("mock:finish");
+            }
+        };
+    }
+
+    @Test
+    public void testVarargs() throws Exception {
+        MockEndpoint end = getMockEndpoint("mock:finish");
+        end.expectedBodiesReceived("Bye Camel with 3 args (sum=6)");
+
+        Object[] arr = new Object[] { "Cam", "el" };
+        sendBody("direct:start", "World", Map.of("myArr", arr));
+
+        assertMockEndpointsSatisfied();
+    }
+
+    @Override
+    protected Registry createCamelRegistry() throws Exception {
+        Registry answer = super.createCamelRegistry();
+        answer.bind("myBean", myBean);
+        return answer;
+    }
+
+    public static class MyBean {
+
+        public String doSomething(Object[] arr, Object... args) {
+            int sum = Integer.parseInt((String) args[0]);
+            sum += Integer.parseInt((String) args[1]);
+            sum += Integer.parseInt((String) args[2]);
+            return "Bye " + arr[0] + arr[1] + " with " + args.length + " args 
(sum=" + sum + ")";
+        }
+    }
+}

Reply via email to