This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch bi in repository https://gitbox.apache.org/repos/asf/camel.git
commit b747b1b2b1e52a8c681e95331e669a381b99ebfb Author: Claus Ibsen <[email protected]> AuthorDate: Mon Dec 15 16:52:36 2025 +0100 CAMEL-22787: camel-bean - Fix bean info to not cache exchange instances. --- .../org/apache/camel/component/bean/BeanInfo.java | 11 +++++-- .../apache/camel/component/bean/BeanInfoTest.java | 35 ++++++++++++++++++++++ 2 files changed, 43 insertions(+), 3 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 cd8010aa75b1..63c974525908 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 @@ -44,6 +44,7 @@ import org.apache.camel.Message; import org.apache.camel.PropertyInject; import org.apache.camel.Variable; import org.apache.camel.Variables; +import org.apache.camel.support.DefaultExchange; import org.apache.camel.support.ObjectHelper; import org.apache.camel.support.builder.ExpressionBuilder; import org.apache.camel.support.language.AnnotationExpressionFactory; @@ -163,12 +164,14 @@ public class BeanInfo { methodMap = Collections.unmodifiableMap(methodMap); // key must be instance based for custom/handler annotations - boolean instanceBased = !operationsWithCustomAnnotation.isEmpty() || !operationsWithHandlerAnnotation.isEmpty(); + boolean instanceBased = (!operationsWithCustomAnnotation.isEmpty() || !operationsWithHandlerAnnotation.isEmpty()); + // do not cache Exchange based beans + instanceBased &= DefaultExchange.class != type; if (instanceBased) { // add new bean info to cache (instance based) component.addBeanInfoToCache(key, this); } else { - // add new bean info to cache (not instance based, favour key2 if possible) + // add new bean info to cache (not instance based, favor key2 if possible) BeanInfoCacheKey k = key2 != null ? key2 : key; component.addBeanInfoToCache(k, this); } @@ -460,10 +463,12 @@ public class BeanInfo { Annotation[] parameterAnnotations = parametersAnnotations[i].toArray(new Annotation[0]); Expression expression = createParameterUnmarshalExpression(method, parameterType, parameterAnnotations); - hasCustomAnnotation |= expression != null; if (expression == null) { expression = strategy.getDefaultParameterTypeExpression(parameterType); } + // this is not entirely correct as the parameter may be a default parameter type and not a custom annotation + // but we need to keep this logic for backwards compatability + hasCustomAnnotation |= expression != null; // whether this parameter is vararg which must be last parameter boolean varargs = method.isVarArgs() && i == size - 1; diff --git a/components/camel-bean/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java b/components/camel-bean/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java index d3c6b65de845..ad4e1529aaef 100644 --- a/components/camel-bean/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java +++ b/components/camel-bean/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java @@ -27,6 +27,7 @@ import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.implementation.MethodDelegation; import net.bytebuddy.implementation.bind.annotation.RuntimeType; import org.apache.camel.CamelContext; +import org.apache.camel.Exchange; import org.apache.camel.Handler; import org.apache.camel.spi.Registry; import org.apache.camel.support.DefaultExchange; @@ -37,7 +38,9 @@ import org.mockito.Mock; import org.mockito.junit.jupiter.MockitoExtension; import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.Mockito.lenient; @@ -127,6 +130,20 @@ public class BeanInfoTest { assertFalse(info2.hasAnyMethodHandlerAnnotation()); } + @Test + public void testChooseExchangeMethod() { + DefaultExchange exchange = new DefaultExchange(context); + BeanInfo info = new BeanInfo(context, MyClassTwo.class); + MethodInfo mi = info.chooseMethod(null, exchange, null); + assertNotNull(mi); + assertTrue(mi.hasCustomAnnotation()); // not really correct; but backwards compatible + assertFalse(mi.hasHandlerAnnotation()); + assertTrue(mi.hasParameters()); + assertFalse(mi.hasBodyParameter()); + assertEquals("myExchangeMethod", mi.getMethod().getName()); + assertEquals(Exchange.class, mi.getMethod().getParameterTypes()[0]); + } + private Object buildProxyObject() { try { return new ByteBuddy() @@ -160,6 +177,24 @@ public class BeanInfoTest { } } + public static class MyClassTwo { + + public void myMethod() { + } + + public String myOtherMethod() { + return ""; + } + + public String myExchangeMethod(Exchange exchange) { + return exchange.getExchangeId(); + } + + public void myBooleanMethod(boolean fool) { + // noop + } + } + public static class MyDerivedClass extends MyClass { @Override public void myMethod() {
