Bug 460587 - Advice not getting applied when an aspect class contains a non-static field that is eligible for LTW advice.
Summary: Advice not getting applied when an aspect class contains a non-static field t...
Status: NEW
Alias: None
Product: AspectJ
Classification: Tools
Component: Runtime (show other bugs)
Version: 1.8.2   Edit
Hardware: PC Windows 7
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2015-02-23 06:13 EST by sridhar thiyagarajan CLA
Modified: 2015-02-23 06:15 EST (History)
1 user (show)

See Also:


Attachments
AopTest - test project (6.92 KB, application/zip)
2015-02-23 06:13 EST, sridhar thiyagarajan CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description sridhar thiyagarajan CLA 2015-02-23 06:13:43 EST
Created attachment 251019 [details]
AopTest - test project

When I tried to work on the samples of aspectJ, I came to observer that aspect class containing a non-static field that is eligible for LTW advice is not getting applied. If I make the members as static, then it works. PFB the error obtained. I am using the version aspectjrt-1.8.2 and aspectjweaver-1.8.5 as javaagent for LTW. I am getting the below error while running the sample project and attaching the same.

Caused by: java.lang.IncompatibleClassChangeError: Expected static method aop.method.MethodAspect.printMethodContext(Lorg/aspectj/lang/ProceedingJoinPoint;)Ljava/lang/Object;
	at aop.method.MyMethodAspectImpl.generated$around$advice$1(Unknown Source)

Please clarify whether the field members of a aspect class should always be static in implementation.

Also, PFB the link for the blog I created for the same problem.

http://stackoverflow.com/questions/28610393/how-to-implement-concrete-aspect-extending-abstract-aspect-having-field-with-ann



Also, adding the email chain related to the same.

---------- Forwarded message ----------
From: Andy Clement <andrew.clement@gmail.com>
Date: Fri, Feb 20, 2015 at 3:15 AM
Subject: Re: [aspectj-dev] How to implement concrete aspect extending abstract aspect having field with annotations eligible for load time weaving in aspect itself
To: AspectJ developer discussions <aspectj-dev@eclipse.org>


Thanks for all the testcode.
Interesting situation. From what I can see the abstract aspects themselves are not being passed to the weaver for weaving. We can see that if you turn on the additional flag in weaver options (-debug):
[AppClassLoader@58644d46] info AspectJ Weaver Version 1.8.4 built on Thursday Nov 6, 2014 at 20:19:21 GMT
[AppClassLoader@58644d46] info register classloader sun.misc.Launcher$AppClassLoader@58644d46
[AppClassLoader@58644d46] info using configuration /Users/aclement/play/sridhar/META-INF/aop.xml
[AppClassLoader@58644d46] info define aspect main.java.aop.extend.ConcreteTracingimpl
[AppClassLoader@58644d46] info define aspect main.java.aop.field.MyFieldAspect
[AppClassLoader@58644d46] debug weaving 'main.java.aop.extend.ConcreteTracingimpl'
[AppClassLoader@58644d46] debug generating class 'main.java.aop.extend.ConcreteTracingimpl'
[AppClassLoader@58644d46] debug weaving 'main.java.aop.field.MyFieldAspect'
[AppClassLoader@58644d46] debug generating class 'main.java.aop.field.MyFieldAspect'
[AppClassLoader@58644d46] debug weaving 'main.java.aop.main.Main'
[AppClassLoader@58644d46] weaveinfo Join point 'field-get(java.lang.String main.java.aop.extend.AbstractTracing.x)' in Type 'main.java.aop.main.Main' (Main.java:11) advised by around advice from 'main.java.aop.field.MyFieldAspect' (FieldAspect.java:7)
<---------- EXTENDS example ---------->
[AppClassLoader@58644d46] debug weaving 'main.java.aop.extend.Test'
[AppClassLoader@58644d46] weaveinfo Join point 'method-execution(void main.java.aop.extend.Test.testMethod())' in Type 'main.java.aop.extend.Test' (Test.java:8) advised by around advice from 'main.java.aop.extend.ConcreteTracingimpl' (AbstractTracing.java)
[AppClassLoader@58644d46] debug generating class 'main.java.aop.extend.Test$AjcClosure1'
[AppClassLoader@58644d46] debug cannot weave 'org.aspectj.lang.NoAspectBoundException'
In trace method of AbstractTracing class : null

Now why it isn’t being passed to the weaver, good question. Possibly it is the re-entrancy guards that are in place to stop the weaver entering itself once already doing something. 
However, I’ve changed things a little and can get it to work, I use a special feature that is hidden in one of the release READMEs.  When you have aspects like you have you can actually define the whole aspect in the XML and just use the code to hold the behavior, you don’t need any aspect annotations.  So if I rewrite your abstract aspects like this:
---
package main.java.aop.field;

class FieldAspect {
  static String getField() {
    return "Andy";
  }
}
—
package main.java.aop.extend;
public class AbstractTracing {

@Field
public static String x;

public static void traceMethod() {
  System.out.println("In trace method of AbstractTracing class : " + x);
}   

}
—
Then this aop.xml:
<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
<aspects>

  <concrete-aspect name="main.java.aop.field.MyFieldAspect">
    <around pointcut="get(@main.java.aop.field.Field * *)" invokeClass="main.java.aop.field.FieldAspect" invokeMethod="getField()"/>
  </concrete-aspect>

  <concrete-aspect name="main.java.aop.extend.ConcreteTracingImpl">
    <around pointcut="execution(@main.java.aop.method.Method * *(..))" invokeClass="main.java.aop.extend.AbstractTracing" invokeMethod="traceMethod()"/>
  </concrete-aspect>

</aspects>
<weaver options="-verbose -showWeaveInfo" />
</aspectj>
(The documentation on this feature is here: http://www.eclipse.org/aspectj/doc/released/README-1612.html )
Now when I run it
[AppClassLoader@58644d46] info AspectJ Weaver Version 1.8.4 built on Thursday Nov 6, 2014 at 20:19:21 GMT
[AppClassLoader@58644d46] info register classloader sun.misc.Launcher$AppClassLoader@58644d46
[AppClassLoader@58644d46] info using configuration /Users/aclement/play/sridhar/META-INF/aop.xml
[AppClassLoader@58644d46] info define aspect main.java.aop.field.MyFieldAspect
[AppClassLoader@58644d46] info define aspect main.java.aop.extend.ConcreteTracingImpl
<---------- EXTENDS example ---------->
[AppClassLoader@58644d46] weaveinfo Join point 'method-execution(void main.java.aop.extend.Test.testMethod())' in Type 'main.java.aop.extend.Test' (Test.java:8) advised by around advice from 'main.java.aop.extend.ConcreteTracingImpl' (no debug info available)
[AppClassLoader@58644d46] weaveinfo Join point 'field-get(java.lang.String main.java.aop.extend.AbstractTracing.x)' in Type 'main.java.aop.extend.AbstractTracing' (AbstractTracing.java:13) advised by around advice from 'main.java.aop.field.MyFieldAspect' (no debug info available)
In trace method of AbstractTracing class : Andy
However, the constraints on the code you point to from the XML (i.e. that the methods need to be static) - I don’t know if that is ok for you or not? The problem you found is definitely a bug (please raise it), I just offer this alternative way of expressing aspects as a workaround.
cheers,
Andy
> On Feb 19, 2015, at 7:52 AM, sridhar thiyagarajan <sridharthiyagarajan@gmail.com> wrote:
>
> Hello,
>
> I am facing a problem while implementing concrete aspect in aspectJ. Below are the related code snippets. I have two abstract aspects - FieldAspect.java and AbstractTracing.java. I am defining concrete aspects in xml - ConcreteTracingimpl and MyFieldAspect and this is not by code. In Main.java, I am calling Test.getTestMethod() and so, before calling this method, as @method is annotated, around advice in AbstractTracing.java gets applied but AbstractTracing.java has also a static field annotated with @field annotation and hence, the field should be initialized with the value andy but it is null.
>
> If an abstract aspect contains fields with annotations and these fields are applicable for load time weaving, how this should be implemented ? Please guide me. Many thanks.
>
> AbstractTracing.java
> package main.java.aop.extend;
> import main.java.aop.field.Field;
> import org.aspectj.lang.annotation.Around;
> import org.aspectj.lang.annotation.Aspect;. 
> import org.aspectj.lang.annotation.Pointcut;
>
> @Aspect
> public abstract class AbstractTracing {
>
> @Field
> static String x;
>
> @Pointcut
> public abstract void trace();
>
> @Around("trace()")
> public void traceMethod() {
>     System.out.println("In trace method of AbstractTracing class : " + x);
>  }   
>
> }
>
> FieldAspect.java
> package main.java.aop.field;
> import org.aspectj.lang.annotation.Around;
> import org.aspectj.lang.annotation.Aspect;
> import org.aspectj.lang.annotation.Pointcut;
> @Aspect
> public abstract class FieldAspect {
> @Pointcut
> public abstract void getField();
>
> @Around("getField()")
> public String getFieldValue() {     
>     return "Andy";
>  }  
> }
>
> aop.xml
> <?xml version="1.0" encoding="UTF-8"?>
> <aspectj>
> <aspects>
> <concrete-aspect name="main.java.aop.extend.ConcreteTracingimpl"
>         extends="main.java.aop.extend.AbstractTracing">
>         <pointcut name="trace"
>             expression="execution(@main.java.aop.method.Method * * (..))" />
>     </concrete-aspect>
> <concrete-aspect name="main.java.aop.field.MyFieldAspect"
>         extends="main.java.aop.field.FieldAspect">
>         <pointcut name="getField" expression="get(@main.java.aop.field.Field * *)" />
>     </concrete-aspect>
> <weaver options="-verbose -showWeaveInfo" />
> </aspectj>
>
> Field.java
> package main.java.aop.field;
> import java.lang.annotation.Documented;
> import java.lang.annotation.ElementType;
> import java.lang.annotation.ElementType;
> import java.lang.annotation.RetentionPolicy;
> import java.lang.annotation.Target;
>
> @Target({ ElementType.FIELD })
> @Retention(RetentionPolicy.RUNTIME)
> @Documented
> public @interface Field {
> }
>
> Method.java
> package main.java.aop.field;
> import java.lang.annotation.Documented;
> import java.lang.annotation.ElementType;
> import java.lang.annotation.ElementType;
> import java.lang.annotation.RetentionPolicy;
> import java.lang.annotation.Target;
>
> @Target({ ElementType.METHOD })
> @Retention(RetentionPolicy.RUNTIME)
> @Documented
> public @interface Method {
> }
>
> Main.java
> package main.java.aop.main;
>
> import main.java.aop.extend.Test;
>
> public class Main {
>
> public static void main(String[] args) {
>
>     System.out.println("<---------- EXTENDS example ---------->");
>     Test.testMethod();
>  }
> }
>
> Test.java
> package main.java.aop.extend;
>
> import main.java.aop.method.Method;
>
> public class Test {
>
> @Method
> public static void testMethod() {
>     System.out.println("calling test method in test class");
>  }
> }
> Thanks,
> Sridhar Thiyagarajan
> _______________________________________________
> aspectj-dev mailing list
> aspectj-dev@eclipse.org
> To change your delivery options, retrieve your password, or unsubscribe from this list, visit
> https://dev.eclipse.org/mailman/listinfo/aspectj-dev

_______________________________________________
aspectj-dev mailing list
aspectj-dev@eclipse.org
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-dev