Bug 281769 - Problem getting the real method when using generic classes in Java
Summary: Problem getting the real method when using generic classes in Java
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Runtime (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows XP
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-06-28 07:53 EDT by Lior Haham CLA
Modified: 2010-03-22 17:49 EDT (History)
2 users (show)

See Also:


Attachments
My crude test app (2.30 KB, application/octet-stream)
2009-10-08 20:12 EDT, Andrew Clement CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Lior Haham CLA 2009-06-28 07:53:47 EDT
Hello, I'm having problem with get the real method in case I use the following scenario.

class GA<T extends GB>
{
  public void action(Object object)
  {
    mService.foo(object);
  }
  public void setService (T service)
  {
    mService = service;
  }  
  private T mService;
}

class GB<T>
{
  public void foo (T param){}
}

class IMP extends GB<Integer>
{
  @Override
  @RunAsJob(parameterNames="param", title="A job foo")
  public void foo (Integer num)
  {
    super.foo(num);
  }
}

TestClass
{
  testGenericInheritance()
  {
    GA ga = new GA<IMP>();
    ga.setService(new IMP());
    ga.action(new Integer(3));
  }
}

I'm using the following spring <aop> configuration:

  <bean id="runAsJobAOP"
    class="jobs.RunAsJobAspect">
    <property name="jobManager" ref="jobManager"/>
  </bean>

  <aop:config>
    <aop:aspect ref="runAsJobAOP">
      <aop:pointcut id="runAsJobMethod"
        expression="@annotation(jobs.RunAsJob)" />
      <aop:before pointcut-ref="runAsJobMethod"
        method="handleBefore" />
      <aop:after-returning pointcut-ref="runAsJobMethod"
        method="handleAfter" />
    </aop:aspect>
  </aop:config>


class RunAsJobAspect have a method "handlebefore", this method will be called when we are call ga.action(), in the test class, because the method foo within IMP class have annotation @RunAsJob.

public void handleBefore (JoinPoint call)
{
  Signature signature = call.getSignature();
  if (signature instanceof MethodSignature)
  {
    MethodSignature methodSignature = (MethodSignature)signature;
  }
}

The problem is that the method signature is of GB.foo() instead of IMP.foo().


Thanks.
Comment 1 Andrew Clement CLA 2009-07-28 00:18:32 EDT
On a rudimentary attempt to recreate this with pure AspectJ, it just works - so it'll have to wait until I have time to create a spring testcase.

Just to note, this is the code I used that worked:
---
import java.lang.annotation.*;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.*;
import org.aspectj.lang.reflect.*;

class GA<T extends GB>
{
  public void action(Object object)
  {
    mService.foo(object);
  }
  public void setService (T service)
  {
    mService = service;
  }  
  private T mService;
}

class GB<T>
{
  public void foo (T param){}
}

class IMP extends GB<Integer>
{
  @Override
  @RunAsJob(parameterNames="param", title="A job foo")
  public void foo (Integer num)
  {
    super.foo(num);
  }
}

public class TestClass {
  public static void main(String []argv) 
  {
    GA ga = new GA<IMP>();
    ga.setService(new IMP());
    ga.action(new Integer(3));
  }
}


@Retention(RetentionPolicy.RUNTIME)
@interface RunAsJob {
  String parameterNames();
  String title();
}

aspect X {
before(): @annotation(RunAsJob) {
  Signature signature = thisJoinPoint.getSignature();
  if (signature instanceof MethodSignature)
  {
    MethodSignature methodSignature = (MethodSignature)signature;
    bSystem.out.println(methodSignature);
  }
}
}
---

it prints: 
"void IMP.foo(Integer)"
Comment 2 Lior Haham CLA 2009-07-29 03:00:45 EDT
Thanks Andy,

The problem start when I am trying to get the annotation @RunAsJob (for getting the title of the job, I use this code for Job logging).
In handleBefore method, my code is:

public void handleBefore (JoinPoint call)
{
  Signature signature = call.getSignature();
  if (signature instanceof MethodSignature)
  {
    Class realInstanceClass = call.getTarget().getClass();
    MethodSignature methodSignature = (MethodSignature)signature;
    realTargetClass.getMethod(methodSignature.getMethod().getName(), 
             methodSignature.getMethod().getParameterTypes()).getAnnotations();

    or 

    realTargetClass.getMethod(methodSignature.getMethod().getName(), 
             methodSignature.getMethod().getParameterTypes()).getAnnotation
             (RunAsJob.class);
  }
}

return null in both time, instead of the annotation from IMP class. Until now I used this code with no problem. Is there something wrong in what I have done, or this is a real bug?

Thanks,
Lior.

Comment 3 Andrew Clement CLA 2009-10-08 20:04:13 EDT
sorry I haven't got back to this sooner.  I created a simple spring configuration around your scenario.  Both the variants of code you included in your last comment worked for me and printed the annotation.  Is your annotation definetly RUNTIME retention?

If you confirm it is, then maybe I'll share the whole app on here and you can tell me what is different between mine and yours.
Comment 4 Andrew Clement CLA 2009-10-08 20:12:44 EDT
Created attachment 149194 [details]
My crude test app

this is a zip of my testcase.  On running it I get:
void IMP.foo(Integer)
public void IMP.foo(java.lang.Integer)
@RunAsJob(parameterNames=param, title=A job foo)
@RunAsJob(parameterNames=param, title=A job foo)
Comment 5 Andrew Clement CLA 2010-03-22 17:49:48 EDT
removing target whilst waiting on feedback