You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@camel.apache.org by "Claus Ibsen (JIRA)" <ji...@apache.org> on 2015/10/24 14:24:27 UTC

[jira] [Assigned] (CAMEL-9243) Invocation of Bean fails when Bean extends and abstract which implements the actual method

     [ https://issues.apache.org/jira/browse/CAMEL-9243?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Claus Ibsen reassigned CAMEL-9243:
----------------------------------

    Assignee: Claus Ibsen

> Invocation of Bean fails when Bean extends and abstract which implements the actual method
> ------------------------------------------------------------------------------------------
>
>                 Key: CAMEL-9243
>                 URL: https://issues.apache.org/jira/browse/CAMEL-9243
>             Project: Camel
>          Issue Type: Bug
>          Components: camel-core
>    Affects Versions: 2.15.3
>            Reporter: Alex Paransky
>            Assignee: Claus Ibsen
>             Fix For: 2.17.0, 2.16.1, 2.15.5
>
>         Attachments: BeanHandlerMethodTest.java
>
>
> The issue described here does NOT exist in 2.15.2 and only manifests in 2.15.3.
> With the following definition of a Bean:
> {code}
>     public interface MyBaseInterface {
>         @Handler
>         String hello(@Body String hi);
>     }
>     public abstract static class MyAbstractBean implements MyBaseInterface {
>         public String hello(@Body String hi) {
>             return "Hello " + hi;
>         }
>         public String doCompute(String input) {
>             fail("Should not invoke me");
>             return null;
>         }
>     }
>     public static class MyConcreteBean extends MyAbstractBean {
>     }
> {code}
> The following test case will fail to invoke the proper method:
> {code}
> public class BeanHandlerMethodTest extends ContextTestSupport {
>     public void testInterfaceBeanMethod() throws Exception {
>         BeanInfo info = new BeanInfo(context, MyConcreteBean.class);
>         Exchange exchange = new DefaultExchange(context);
>         MyConcreteBean pojo = new MyConcreteBean();
>         MethodInvocation mi = info.createInvocation(pojo, exchange);
>         assertNotNull(mi);
>         assertEquals("hello", mi.getMethod().getName());
>     }
> {code}
> The issue is how BeanInfo.introspect determines which methods are available to be invoked.
> At line 344, if the class is public, the interface methods are added to the list:
> {code}
>         if (Modifier.isPublic(clazz.getModifiers())) {
>             // add additional interface methods
>             List<Method> extraMethods = getInterfaceMethods(clazz);
>             for (Method target : extraMethods) {
>                 for (Method source : methods) {
>                     if (ObjectHelper.isOverridingMethod(source, target, false)) {
>                         overrides.add(target);
>                     }
>                 }
>             }
>             // remove all the overrides methods
>             extraMethods.removeAll(overrides);
>             methods.addAll(extraMethods);
>         }
> {code}
> However, all the methods from the interface are "abstract".  Later, when the real implementation is encountered as the code crawls up the tree, the abstract method is not replaced:
> Line 390:
> {code}
>         MethodInfo existingMethodInfo = overridesExistingMethod(methodInfo);
>         if (existingMethodInfo != null) {
>             LOG.trace("This method is already overridden in a subclass, so the method from the sub class is preferred: {}", existingMethodInfo);
>             return existingMethodInfo;
>         }
> {code}
> Finally, during the invocation, the following was added as part of 2.15.3 release:
> Line 561:
> {code}
>         removeAllAbstractMethods(localOperationsWithBody);
>         removeAllAbstractMethods(localOperationsWithNoBody);
>         removeAllAbstractMethods(localOperationsWithCustomAnnotation);
>         removeAllAbstractMethods(localOperationsWithHandlerAnnotation);
> {code}
> As a result, the abstract method is removed and not invoked.
> I think the fix should be to see if the existingMethodInfo references an "abstract' method and if it does and methodInfo does not, replace the existingMethodInfo with methodInfo in the collection.
> This would preserve the preferences implied with the rest of the code while properly replacing the abstract method with their proper implementations.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)