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)