How to implement concrete aspect extending abstract aspect having field with annotations eligible for load time weaving in aspect itself

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

How to implement concrete aspect extending abstract aspect having field with annotations eligible for load time weaving in aspect itself

sridhar thiyagarajan

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
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-dev
Reply | Threaded
Open this post in threaded view
|

Re: How to implement concrete aspect extending abstract aspect having field with annotations eligible for load time weaving in aspect itself

Andy Clement
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 <[hidden email]> 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
[hidden email]
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
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-dev
Reply | Threaded
Open this post in threaded view
|

Re: How to implement concrete aspect extending abstract aspect having field with annotations eligible for load time weaving in aspect itself

sridhar thiyagarajan

Many thanks a lot !!! .. Andy. You made my day great !. It worked with static members as per your sample. I will anyway try to raise a bug for not supporting the non-static members.


Thanks a lot again.

Sridhar Thiyagarajan




Thanks.

Sridhar Thiyagarajan

On Fri, Feb 20, 2015 at 3:15 AM, Andy Clement <[hidden email]> wrote:
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 <[hidden email]> 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
[hidden email]
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
[hidden email]
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
[hidden email]
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/aspectj-dev