This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/master by this push: new 3e1a63b [CAMEL-15278] Make sure the @Handler annotation is seen on proxied classes 3e1a63b is described below commit 3e1a63b5cf03faa97aff8255518a1814b821492e Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Wed Jul 8 14:37:54 2020 +0200 [CAMEL-15278] Make sure the @Handler annotation is seen on proxied classes --- components/camel-bean/pom.xml | 12 +++ .../org/apache/camel/component/bean/BeanInfo.java | 16 ++++ .../apache/camel/component/bean/BeanInfoTest.java | 104 +++++++++++++++++++++ 3 files changed, 132 insertions(+) diff --git a/components/camel-bean/pom.xml b/components/camel-bean/pom.xml index 722ee82..6f0023f 100644 --- a/components/camel-bean/pom.xml +++ b/components/camel-bean/pom.xml @@ -40,5 +40,17 @@ <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.junit.jupiter</groupId> + <artifactId>junit-jupiter</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-junit-jupiter</artifactId> + <version>${mockito-version}</version> + <scope>test</scope> + </dependency> + </dependencies> </project> 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 16a3818..0491065 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 @@ -42,6 +42,7 @@ import org.apache.camel.Header; import org.apache.camel.Headers; import org.apache.camel.Message; import org.apache.camel.PropertyInject; +import org.apache.camel.RuntimeCamelException; import org.apache.camel.spi.Registry; import org.apache.camel.support.ObjectHelper; import org.apache.camel.support.builder.ExpressionBuilder; @@ -93,6 +94,17 @@ public class BeanInfo { } public BeanInfo(CamelContext camelContext, Class<?> type, Method explicitMethod, ParameterMappingStrategy strategy) { + while (type.isSynthetic()) { + type = type.getSuperclass(); + if (explicitMethod != null) { + try { + explicitMethod = type.getDeclaredMethod(explicitMethod.getName(), explicitMethod.getParameterTypes()); + } catch (NoSuchMethodException e) { + throw new RuntimeCamelException("Unable to find a method " + explicitMethod + " on " + type, e); + } + } + } + this.camelContext = camelContext; this.type = type; this.strategy = strategy; @@ -405,6 +417,10 @@ public class BeanInfo { boolean hasCustomAnnotation = false; boolean hasHandlerAnnotation = org.apache.camel.util.ObjectHelper.hasAnnotation(method.getAnnotations(), Handler.class); + if (!hasHandlerAnnotation) { + + } + int size = parameterTypes.length; if (LOG.isTraceEnabled()) { LOG.trace("Creating MethodInfo for class: {} method: {} having {} parameters", clazz, method, size); 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 new file mode 100644 index 0000000..7a12ca1 --- /dev/null +++ b/components/camel-bean/src/test/java/org/apache/camel/component/bean/BeanInfoTest.java @@ -0,0 +1,104 @@ +/* + * 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 net.bytebuddy.ByteBuddy; +import net.bytebuddy.description.modifier.Ownership; +import net.bytebuddy.description.modifier.SyntheticState; +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.Handler; +import org.apache.camel.spi.Registry; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.Mock; +import org.mockito.junit.jupiter.MockitoExtension; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.mockito.Mockito.lenient; + +@ExtendWith(MockitoExtension.class) +public class BeanInfoTest { + + public static class MyClass { + @Handler + public void myMethod() { + } + } + + public static class MyDerivedClass extends MyClass { + @Override + public void myMethod() { + } + } + + @Mock + private CamelContext context; + + @Mock + private Registry registry; + + private BeanComponent beanComponent; + + @BeforeEach + public void setup() { + beanComponent = new BeanComponent(); + lenient().when(context.getComponent("bean", BeanComponent.class)).thenReturn(beanComponent); + lenient().when(context.getRegistry()).thenReturn(registry); + lenient().when(registry.lookupByNameAndType(BeanConstants.BEAN_PARAMETER_MAPPING_STRATEGY, ParameterMappingStrategy.class)) + .thenReturn(null); + } + + @Test + public void testHandlerClass() throws Exception { + BeanInfo info = new BeanInfo(context, MyClass.class.getMethod("myMethod")); + assertTrue(info.hasAnyMethodHandlerAnnotation()); + } + + @Test + public void testHandlerOnSyntheticProxy() throws Exception { + Object proxy = new ByteBuddy() + .subclass(MyClass.class) + .modifiers(SyntheticState.SYNTHETIC, Visibility.PUBLIC, Ownership.STATIC) + .method(named("myMethod")) + .intercept(MethodDelegation.to( + new Object() { + @RuntimeType + public void intercept() throws Exception { + } + })) + .make() + .load(getClass().getClassLoader()) + .getLoaded() + .getDeclaredConstructor() + .newInstance(); + BeanInfo info = new BeanInfo(context, proxy.getClass().getMethod("myMethod")); + assertTrue(info.hasAnyMethodHandlerAnnotation()); + } + + @Test + public void testHandlerOnDerived() throws Exception { + BeanInfo info = new BeanInfo(context, MyDerivedClass.class.getMethod("myMethod")); + assertFalse(info.hasAnyMethodHandlerAnnotation()); + } + +}