Announcement Announcement Module
Collapse
No announcement yet.
No access to getParameterTypes() on Signature Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • No access to getParameterTypes() on Signature

    Perhaps someone in the forum can help. I cannot seem to get access to getParameterTypes() using Spring AOP and AspectJ.

    I have put method aspects on a class and have three methods.

    public class SampleService {

    @Trace(context="myapp", message="this is my message")
    public void method() throws Exception{

    }
    @Trace(context="myapp", message="this is my message 2")
    public void method(String arg1) throws Exception{

    }

    @Trace(context="myapp", message="this is my message 3")
    public void method(String arg1, int arg2) throws Exception{

    }
    }


    The trace annotation class is

    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;

    @Retention(RetentionPolicy.RUNTIME)
    public @interface Trace {
    String context();
    String message();
    }


    The aop.xml is

    <!DOCTYPE aspectj PUBLIC
    "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
    <aspectj>

    <weaver>
    <!-- only weave classes in our application-specific packages -->
    <include within="com.xxx.test.*" />
    </weaver>

    <aspects>
    <aspect name="com.xxx.tracing.TraceAspect" />
    </aspects>

    </aspectj>

    This issue is that I cannot access the parameterTypes() method from TraceAspect.

    From the trace aspect Annotation -

    @Aspect
    public class TraceAspect {

    @Around("methodsToBeTraced()")
    public void trace(ProceedingJoinPoint pjp) throws Throwable {
    System.out.println(pjp.getTarget());
    System.out.println(pjp.getSignature());
    System.out.println(pjp.getArgs().length);
    String methodName = pjp.getSignature().getName();
    // try to get parameter type
    System.out.println("Args = "+getParameterTypes(pjp));
    // next method fails
    System.out.println("Args2 = "+getParameterTypes2(pjp));
    // the next line of code needs to be made generic with parameterTypes.
    // working on using reflection to find it
    Method method = pjp.getTarget().getClass().getDeclaredMethod(metho dName, getParameterTypes(pjp));
    System.out.println(method);
    Annotation annotation = method.getAnnotation(Trace.class);

    if(annotation instanceof Trace){
    Trace myAnnotation = (Trace) annotation;
    System.out.println("name: " + myAnnotation.context());
    System.out.println("value: " + myAnnotation.message());
    }

    }
    // the issue with this method is that primitives are not handled
    private Class[] getParameterTypes(JoinPoint jp) {
    Object[] args = jp.getArgs();
    Class[] types = new Class[args.length];
    for(int i=0;i<args.length;i++) {
    types[i] = args[i].getClass();
    }
    return types;
    }


    private Class[] getParameterTypes2(JoinPoint jp) throws Exception{
    Method aMethod = jp.getSignature().getClass().getMethod("getParamet erTypes", new Class[] {});
    Class[] parameterTypes = (Class[])aMethod.invoke(jp.getSignature().getClass(), new Object[] {});
    return new Class[] {};

    }

    @Pointcut("execution(public * *(..))")
    private void anyPublicOperation() {}

    @Pointcut("execution(private * *(..))")
    private void anyPrivateOperation() {}

    @Pointcut("execution(protected * *(..))")
    private void anyProtectedOperation() {}

    @Pointcut("anyPublicOperation() || anyProtectedOperation() || anyPrivateOperation()")
    private void methodsToBeTraced() {}
    }


    When I execute this from my SpringTraceTest class

    package com.xxx.test;

    import junit.framework.TestCase;

    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlAp plicationContext;

    public class SpringTraceTest extends TestCase {

    public static void main(String[] args) throws Exception {

    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext .xml", SpringTraceTest.class);

    SampleService sampleService
    = (SampleService) ctx.getBean("testService");

    // the profiling aspect is 'woven' around this method execution
    sampleService.method();

    sampleService.method("foo");

    sampleService.method("foo", 1);
    }

    }


    I get a stack trace -

    Exception in thread "main" java.lang.IllegalAccessException: Class com.xxx.tracing.TraceAspect can not access a member of class org.aspectj.runtime.reflect.CodeSignatureImpl with modifiers "public"
    at sun.reflect.Reflection.ensureMemberAccess(Reflecti on.java:77)
    at java.lang.reflect.Method.invoke(Method.java:591)
    at com.xxx.tracing.TraceAspect.getParameterTypes2(Tra ceAspect.java:50)
    at com.xxx.tracing.TraceAspect.trace(TraceAspect.java :23)
    at com.xxx.test.SampleService.method(SampleService.ja va:13)
    at com.xxx.test.SpringTraceTest.main(SpringTraceTest. java:18)

    I believe this is due to the implementation of the inner class with the JoinPoint. I think Spring should properly expose the getParameterTypes method.

    But, if someone has some other suggestion to get the method based on the join point or some other way, I would appreciate the help.

  • #2
    Why going thru getClass().getMethod() while the JP signature should be a CodeSignature and thus has the getParameterTypes() method ?

    CodeSignature cs = (CodeSignature)jp.getSignature();
    cs.getParameterTypes() ;

    Comment


    • #3
      Your solution worked.

      Thanks. Sometimes you just get stuck.

      Comment

      Working...
      X