Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [aspectj-users] Mixins with @DeclareParents (M5)

Thanks!  I grabbed the latest dev build and the exceptions disappear.

But, can I make the advice non-static? I noticed that @DeclareParents requires "public static...". I was wondering about that and it, indeed, means that the advice is static (I can create two instances of Test/Test3, call t0.setId(123) and t1.getId() now returns 123), unlike the standard "declare parents :".

Andy Clement wrote:

I have just fixed a but that looks very much like your problem.

See bugzilla 117681 "VerifyError when using annotations to define inter-type"
 https://bugs.eclipse.org/bugs/show_bug.cgi?id=117681

The fix is in the latest AJ dev build - and I hope we can deliver it
in AJDT tomorrow.

Andy.

On 23/11/05, Brian Ericson <bme@xxxxxxxx> wrote:
Thanks for the response!

Sorry -- the "long test { getId(); } was mis-translated as I simplified
it for the purposes of the post and should have been "public long test()
{ return getId(); } -- I'd hoped to be able to call the methods provided
by advice in the advised classes, but while this worked outside of
Eclipse, Eclipse+AJDT does not appear to like it (I'll try your
suggestion to make ADJT the editor for all Java files).  I've since
removed that test, as I'm still trying to get basic annotation-style
declare parents working.

Where I'm stuck now is the java.lang.VerifierError.  To be clear, I'm
trying three scenarios.  The first, using the "Adrian-style" (in his
blog linked to previously) does not work:
PersistentEntity.java
---------------------
package test;

public @interface PersistentEntity { }

PersistentEntityAspect.java
---------------------------
package test;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;

@Aspect
public class PersistentEntityAspect {
  public interface Persistent {
     long getId();
     void setId(long id);
  }

  public class PersistentImpl implements Persistent {
     long id = 0;

     public long getId() { return id; }
     public void setId(long id) { this.id = id; }
  }

  @DeclareParents("@test.PersistentEntity test.*")
  public static Persistent introduced = new
PersistentEntityAspect().new PersistentImpl();
}

Test.java
---------
package test;

@PersistentEntity
public class Test { }

The second, using the "old-style" approach works:
PersistentEntity2.java
----------------------
package test;

public @interface PersistentEntity2 { }

PersistentEntityAspect2.aj
--------------------------
package test;

public aspect PersistentEntityAspect2 {
  public interface Persistent {
     long getId();
     void setId(long id);
  }

  declare parents : @PersistentEntity2 * implements Persistent;

  long Persistent.id = 0;

  public long Persistent.getId() { return id; }
  public void Persistent.setId(long id) { this.id = id; }
}

Test2.java
----------
package test;

@PersistentEntity2
public class Test2 { }

The third, using the "moody-style" also does not work:
PersistentEntity3.java
----------------------
package test;

public @interface PersistentEntity3 { }

Persistent.java
---------------
package test;

public interface Persistent {
  long getId();
  void setId(long id);
}

PersistentImpl.java
-------------------
package test;

public class PersistentImpl implements Persistent {
  long id = 0;

  public long getId() { return id; }
  public void setId(long id) { this.id = id; }
}

PersistentEntityAspect3.java
----------------------------
package test;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;

@Aspect
public class PersistentEntityAspect3 {
  @DeclareParents("@test.PersistentEntity3 test.*")
  public static Persistent introduced = new PersistentImpl();
}

Test3.java
----------
package test;

@PersistentEntity3
public class Test3 { }

All three compile, and Test, Test2, and Test3 each have the AspectJ
markers indicating advice, but the following test:
TestTests.java
--------------
package test;

public class TestTests {
  public static void main(String[] args) {
     try {
        final Test test = new Test();
        System.out.println("test"+((test instanceof
PersistentEntityAspect.Persistent) ? " " : "not ")+"advised");
     }
     catch (Throwable t) {
        System.out.println("test threw an exception!");
        t.printStackTrace();
     }

     try {
        final Test2 test2 = new Test2();
        System.out.println("test2"+((test2 instanceof
PersistentEntityAspect2.Persistent) ? " " : "not ")+"advised");
     }
     catch (Throwable t) {
        System.out.println("test2 threw an exception!");
        t.printStackTrace();
     }

     try {
        final Test3 test3 = new Test3();
        System.out.println("test3"+((test3 instanceof Persistent) ? " "
: "not ")+"advised");
     }
     catch (Throwable t) {
        System.out.println("test3 threw an exception!");
        t.printStackTrace();
     }
  }
}

gives the following result:
test threw an exception!
java.lang.VerifyError: (class: test/Test, method: setId signature: (J)V)
Register pair 0/1 contains wrong type
       at test.TestTests.main(TestTests.java:6)
test2 advised
test3 threw an exception!
java.lang.VerifyError: (class: test/Test3, method: setId signature:
(J)V) Register pair 0/1 contains wrong type
       at test.TestTests.main(TestTests.java:24)

I'm not sure what I'm doing wrong here...

Alexandru Popescu wrote:

I am not sure about this, but the PersistentImpl shouldn't be declared
as static?


About Eclipse/AJDT: if you want to use directly the ITDs, I think you
should set the AJDT editor as the default for all .java files.

However, I don't understand how this would look like:

[code]
For example, Test.java could not look as follows:
public Test {
 long test { return getId(); }
}
[/code]

Haven't you missed something? (some paranthesis, I guess).

./alex
--
.w( the_mindstorm )p.

#: Brian Ericson changed the world a bit at a time by saying on
11/23/2005 7:30 AM :#

Some progress...  Moving everything to a "test" package and changing
the declaration to:
@DeclareParents("@test.PersistentEntity test.*")
is enough to get AspectJ markers in Eclipse.  However, an attempt to
construct an instance of Test fails with the following exception:
java.lang.VerifyError: (class: test/Test, method: setId signature:
(J)V) Register pair 0/1 contains wrong type

I also reworked the "moody" example (in the documentation and sited
in a thread below) using a Persistent interface and PersistentImpl
implementation outside of the aspect, allowing me to do the following:
package test;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;

@Aspect
public class PersistentEntityAspect {
  @DeclareParents("@test.PersistentEntity test.*")
  public static Persistent introduced = new PersistentImpl();
}

This fails with the same exception above.  What am I doing wrong?
This works for Adrian... (see
http://www-128.ibm.com/developerworks/java/library/j-aopwork8/ ).

Brian Ericson wrote:

I'm trying to implement mixins using the @Aspect/@DeclareParents
annotations.  To begin with, the following works:
PersistentEntity.java:
public @interface PersistentEntity { }

PersistentEntityAspect.aj:
public aspect PersistentEntityAspect {
 public interface Persistent {
    long getId();
    void setId(long id);
 }

 declare parents : @PersistentEntity * implements Persistent;

 long Persistent.id = 0;

 public long Persistent.getId() { return id; }
 public void Persistent.setId(long id) { this.id = id; }
}

Test.java:
@PersistentEntity
public class Test { }

Using Jython, I can see that Test implements
PersistentEntityAspect.Persistent and can call both getId() and
setId().

The following does not work (replacing PersistentEntityAspect.aj
with PersistentEntityAspect.java):
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.DeclareParents;

@Aspect
public class PersistentEntityAspect {
 public interface Persistent {
    long getId();
    void setId(long id);
 }

 public class PersistentImpl implements Persistent {
    long id;
        public long getId() { return id; }
    public void setId(long id) { this.id = id; }
 }

 @DeclareParents("@PersistentEntity *")
 public static Persistent introduced = new
PersistentEntityAspect().new PersistentImpl();
}

Test is not advised and does not implement any interface.  (I did
use the recent thread
http://dev.eclipse.org/mhonarc/lists/aspectj-users/msg05032.html as
reference, but this neither compiled (... introduced = new
MoodyImpl();) nor did I get the advice bit working out.  I must be
doing something simple wrong (maybe I need to post-compile the
result to weave it or use load-time weaving?  I'm not sure how to do
either (more research!))...

Other questions...  Eclipse/AJDT does not allow me to use methods
introduced by advice.  For example, Test.java could not look as
follows:
public Test {
 long test { return getId(); }
}

This actually compiles and runs correctly using ajc, but won't get
compile in the IDE (The method getId() is undefined...).

Also, how're people using AspectJ with Maven 2?  Confessing to be a
newbie to both AspectJ and Maven, I'm currently "tricking" it by
using ajc as my java compiler.
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users
_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users

_______________________________________________
aspectj-users mailing list
aspectj-users@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/aspectj-users


Back to the top