Bug 390269 - AbstractMethodError when calling generic ITD method
Summary: AbstractMethodError when calling generic ITD method
Status: RESOLVED FIXED
Alias: None
Product: AspectJ
Classification: Tools
Component: Compiler (show other bugs)
Version: DEVELOPMENT   Edit
Hardware: Macintosh Mac OS X
: P3 normal (vote)
Target Milestone: 1.7.2   Edit
Assignee: aspectj inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-09-24 16:06 EDT by Matthew Adams CLA
Modified: 2013-01-25 20:04 EST (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Adams CLA 2012-09-24 16:06:22 EDT
After upgrading to ajc 1.7.2-BUILD-SNAPSHOT, I'm now getting an AbstractMethodError in a unit test:

============
testCreateUser(app.domain.test.unit.UserTest)  Time elapsed: 0.098 sec  <<< FAILURE!
java.lang.AbstractMethodError: app.domain.model.Person.getId()Ljava/lang/Object;
        at com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect.ajc$interMethod$com_scispike_foundation_domain_aspectj_trait_persistence_PersistableAspect$com_scispike_foundation_domain_aspectj_trait_persistence_PersistableAspect$I$hashCode(PersistableAspect.aj:91)
        at app.domain.model.Person.hashCode(Person.java:1)
        at java.util.WeakHashMap.put(WeakHashMap.java:401)
        at org.apache.commons.lang3.builder.ToStringStyle.register(ToStringStyle.java:182)
        at org.apache.commons.lang3.builder.ToStringStyle.appendClassName(ToStringStyle.java:1444)
        at org.apache.commons.lang3.builder.ToStringStyle.appendStart(ToStringStyle.java:369)
        at org.apache.commons.lang3.builder.ToStringBuilder.<init>(ToStringBuilder.java:263)
        at org.apache.commons.lang3.builder.ReflectionToStringBuilder.<init>(ReflectionToStringBuilder.java:456)
        at org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:282)
        at org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:145)
        at com.scispike.foundation.domain.aspectj.trait.basic.StringifiableAspect.buildString(StringifiableAspect.aj:63)
        at com.scispike.foundation.domain.aspectj.trait.basic.StringifiableAspect.ajc$interMethod$com_scispike_foundation_domain_aspectj_trait_basic_StringifiableAspect$com_scispike_foundation_domain_aspectj_trait_basic_StringifiableAspect$S$toString(StringifiableAspect.aj:41)
        at app.domain.model.Person.toString(Person.java:1)
        at java.lang.String.valueOf(String.java:2826)
        at java.util.Arrays.toString(Arrays.java:4071)
        at com.scispike.foundation.domain.aspectj.validation.ApacheBvalMethodValidationAspect.buildMessage(ApacheBvalMethodValidationAspect.aj:74)
        at com.scispike.foundation.domain.aspectj.validation.ApacheBvalMethodValidationAspect.ajc$before$com_scispike_foundation_domain_aspectj_validation_ApacheBvalMethodValidationAspect$2$68590448(ApacheBvalMethodValidationAspect.aj:147)
        at app.domain.model.User.setPerson(User.java:45)
        at app.domain.model.User.<init>(User.java:37)
        at app.domain.test.unit.UserTest.create(UserTest.java:23)
        at app.domain.test.unit.UserTest.create(UserTest.java:19)
        at app.domain.test.unit.UserTest.testCreateUser(UserTest.java:40)
============

If I remove the annotation that is causing the application of ApacheBvalMethodValidationAspect (by removing @NotNull on User#setPerson(Person), the code executes ok during unit testing, but then fails during integration testing:

============
testPersistEach(app.domain.test.integration.mongo.UserRepositoryIntegrationTest)  Time elapsed: 0.084 sec  <<< FAILURE!
java.lang.AbstractMethodError: app.domain.model.User.getId()Ljava/lang/Object;
        at com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect.ajc$interMethod$com_scispike_foundation_domain_aspectj_trait_persistence_PersistableAspect$com_scispike_foundation_domain_aspectj_trait_persistence_PersistableAspect$I$getIdString(PersistableAspect.aj:53)
        at app.domain.model.User.getIdString(User.java:1)
        at app.domain.test.integration.mongo.UserRepositoryIntegrationTest.testPersistEach(UserRepositoryIntegrationTest.java:31)
============

The codebase is available to Andy; it's the same as that used to diagnose & resolve https://bugs.eclipse.org/bugs/show_bug.cgi?id=389750 and https://bugs.eclipse.org/bugs/show_bug.cgi?id=389752

This bug is **NOT** on the "master" branch, it is on the "features/test-persistence-trait" branch.
Comment 1 Matthew Adams CLA 2012-09-25 12:09:26 EDT
BTW, I should say the repo is available to Andy **Clement**...  Andrew Eisenberg, if you want access, I can give it to you, too.  :)
Comment 2 Matthew Adams CLA 2012-09-25 12:17:34 EDT
After looking at this further, there is one common feature to both failing method calls.  Each failing call is from within a method on the class that received the ITD being called.  In the first failure case, Person#hashCode() is an ITD method that is calling this.getId(), which is a generic ITD method.  In the second case, Person#getIdString() (a non-generic ITD method) is calling this.getId(), again, a generic ITD method.

I'll see if I can create a small test case.
Comment 3 Matthew Adams CLA 2012-09-26 10:07:29 EDT
I'm still trying to repro with a small test case but haven't been able to.  No dice so far.  Andy Clement, if you could have a look at the codebase, I'd appreciate it.  Meantime, I'll keep trying.
Comment 4 Andrew Clement CLA 2012-09-27 14:09:04 EDT
i switch to the branch you mention, I ran 'mvn -X clean test' and although I see testCreateUser fail, I don't see an abstractmethoderror or an ajcore file - what am I doing wrong?
Comment 5 Andrew Clement CLA 2012-09-27 16:08:27 EDT
I then tried mvn eclipse:eclipse and imported the result but one of the projects won't build with errors:

PersonRepositoryIntegrationTest.java	/foundation-mongo-domain-test/src/test/java/app/domain/test/integration/mongo	line 29	Java Problem
The method getId() is undefined for the type User	UserRepositoryIntegrationTest.java	/foundation-mongo-domain-test/src/test/java/app/domain/test/integration/mongo	line 36	Java Problem
The method getId() is undefined for the type User	UserRepositoryIntegrationTest.java	/foundation-mongo-domain-test/src/test/java/app/domain/test/integration/mongo	line 36	Java Problem
The method getIdString() is undefined for the type User	UserRepositoryIntegrationTest.java	/foundation-mongo-domain-test/src/test/java/app/domain/test/integration/mongo	line 31	Java Problem

is that expected?
Comment 6 Matthew Adams CLA 2012-09-27 17:22:05 EDT
What are you seeing when testCreateUser fails?  I reran 'mvn clean install' in with the latest on the branch and got this (in foundation/test-client/mongo/domain/target/surefire-reports/TestSuite.txt):


Tests run: 5, Failures: 3, Errors: 0, Skipped: 0, Time elapsed: 0.603 sec <<< FAILURE!
testCreateUser(app.domain.test.unit.UserTest)  Time elapsed: 0.096 sec  <<< FAILURE!
java.lang.AbstractMethodError: app.domain.model.Person.getId()Ljava/lang/Object;
        at com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect.ajc$interMethod$com_scispike_foundation_domain_aspectj_trait_persistence_PersistableAspect$com_scispike_foundation_domain_aspectj_trait_persistence_PersistableAspect$I$hashCode(PersistableAspect.aj:91)
        at app.domain.model.Person.hashCode(Person.java:1)
        at java.util.WeakHashMap.put(WeakHashMap.java:401)
        at org.apache.commons.lang3.builder.ToStringStyle.register(ToStringStyle.java:182)
        at org.apache.commons.lang3.builder.ToStringStyle.appendClassName(ToStringStyle.java:1444)
        at org.apache.commons.lang3.builder.ToStringStyle.appendStart(ToStringStyle.java:369)
        at org.apache.commons.lang3.builder.ToStringBuilder.<init>(ToStringBuilder.java:263)
        at org.apache.commons.lang3.builder.ReflectionToStringBuilder.<init>(ReflectionToStringBuilder.java:456)
        at org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:282)
        at org.apache.commons.lang3.builder.ReflectionToStringBuilder.toString(ReflectionToStringBuilder.java:145)
        at com.scispike.foundation.domain.aspectj.trait.basic.StringifiableAspect.buildString(StringifiableAspect.aj:63)
        at com.scispike.foundation.domain.aspectj.trait.basic.StringifiableAspect.ajc$interMethod$com_scispike_foundation_domain_aspectj_trait_basic_StringifiableAspect$com_scispike_foundation_domain_aspectj_trait_basic_StringifiableAspect$S$toString(StringifiableAspect.aj:41)
        at app.domain.model.Person.toString(Person.java:1)
        at java.lang.String.valueOf(String.java:2826)
        at java.util.Arrays.toString(Arrays.java:4071)
        at com.scispike.foundation.domain.aspectj.validation.ApacheBvalMethodValidationAspect.buildMessage(ApacheBvalMethodValidationAspect.aj:74)
        at com.scispike.foundation.domain.aspectj.validation.ApacheBvalMethodValidationAspect.ajc$before$com_scispike_foundation_domain_aspectj_validation_ApacheBvalMethodValidationAspect$2$68590448(ApacheBvalMethodValidationAspect.aj:147)
        at app.domain.model.User.setPerson(User.java:45)
        at app.domain.model.User.<init>(User.java:37)
        at app.domain.test.unit.UserTest.create(UserTest.java:23)
        at app.domain.test.unit.UserTest.create(UserTest.java:19)
        at app.domain.test.unit.UserTest.testCreateUser(UserTest.java:40)

I show no files checked out.  Can you show me what you're getting?

I don't use 'mvn eclipse:eclipse', but instead import the project as an existing Maven project.  It's weird that mvn compiles for you but eclipse complains...I have no project errors after File\Import\Maven\Existing Maven project.

I always consider Maven to be The One Truth and ignore the myriad of errors I tend see in eclipse (at least until I do a Project\Clean... or project\Maven\Update Project).

I'm using STS 3.0.0.RELEASE, and added the snapshot AJDT eclipse update site (AJDT Update Site - http://download.eclipse.org/tools/ajdt/42/dev/update) to get the latest & greatest AJDT.  Here are some relative highlights from Help\Install New Software...\What is already installed\Installed Software:

  AspectJ Development Tools	2.2.2.e42x-20120924-0800	org.eclipse.ajdt.feature.group	Eclipse AspectJ Development Tools

  m2e - Maven Integration for Eclipse	1.1.0.20120530-0009	org.eclipse.m2e.feature.feature.group	Eclipse.org - m2e

  Maven Integration for AJDT (Optional)	0.13.0.201107281640	org.maven.ide.eclipse.ajdt.feature.feature.group	Sonatype, Inc.

  Spring Tool Suite	3.0.0.201208091018-RELEASE-e42	org.springsource.sts.ide	null
Comment 7 Andrew Clement CLA 2012-09-28 13:14:35 EDT
it looks like Person is missing a bridge method from Object getId() to String getId().
Comment 8 Andrew Clement CLA 2012-09-29 00:48:37 EDT
ok, fixed this.

It was bridge method related.

the method added to person was 'String getId()' and walking up the hierarchy we hit a 'String getId()' in the interface and assumed no bridge method required. What the code didn't allow for is another candidate higher up 'Object getId()'.  So it failed to create the bridge method and AbstractMethodError is the result.

The fix is to search for all candidates for bridging, not just 'the first one'.

I've tested this on your codebase and it fixes it.

New 1.7.2 snapshot pushed to the spring maven repo.
Comment 9 Matthew Adams CLA 2012-09-29 09:22:58 EDT
Thanks Andy!  I'm glad you could find the problem so quickly.
Comment 10 Matthew Adams CLA 2012-10-02 12:24:49 EDT
After reintroducing generics back into the mix (see HEAD in repo), I'm now getting compilation errors in project foundation/test-client/mongo/domain, but oddly, up in project foundation/domain, no compilation errors are not present.

The only difference between the two projects that I can figure is that foundation/domain compiles and applies the aspects in the same project (demonstrated via class foundation/domain/src/test/java/.../MongoStringPerson.java), whereas foundation/test-client/mongo/domain applies aspects from foundation/domain to target classes via the aspectpath.

For example, look at the compiler output of Address v. Generation.  Address and Generation don't differ in terms of the aspect being applied (PersistableMongoAspect).  Address is getting all introduced methods from all superinterfaces of interface "StringMongo", but Generation is not getting methods from StringMongo's root superinterface "I":

...Address is getting everything it should...

[INFO] Extending interface set for type 'app.domain.model.Address' (Address.java) to include 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo' (PersistableMongoAspect.aj)
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped field from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'org.springframework.data.mongodb.core.MongoTemplate com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$Mongo.mongo')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped field from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'java.lang.String com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.id')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped field from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'long com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.version')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'java.lang.String com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.id()')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'java.lang.String com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.idString()')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'void com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.idString(java.lang.String)')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'long com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.version()')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'void com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.version(long)')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'java.lang.Object com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.getOid()')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'java.lang.String com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$S.getId()')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'void com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$S.setId(java.lang.String)')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'long com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.getVersion()')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'void com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.setVersion(long)')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'boolean com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.equals(java.lang.Object)')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'boolean com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.equals(com.scispike.foundation.domain.trait.interfaces.persistence.Persistable<>)')
[INFO] Type 'app.domain.model.Address' (Address.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'int com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.hashCode()')

...now Generation...note absence of introductions from interface "I":

[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped field from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'org.springframework.data.mongodb.core.MongoTemplate com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$Mongo.mongo')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped field from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'java.lang.String com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.id')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped field from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'long com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.version')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'java.lang.String com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.id()')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'java.lang.String com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.idString()')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'void com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.idString(java.lang.String)')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'long com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.version()')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect' (PersistableMongoAspect.aj:'void com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo.version(long)')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'java.lang.String com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$S.getId()')
[INFO] Type 'app.domain.model.Generation' (Generation.java) has intertyped method from 'com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect' (PersistableAspect.aj:'void com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$S.setId(java.lang.String)')

This results, understandably, in a subsequent compiler error:

[ERROR] The type app.domain.model.Generation must implement the inherited abstract method com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.equals(Lcom/scispike/foundation/domain/trait/interfaces/persistence/Persistable;)
[ERROR] The type app.domain.model.Generation must implement the inherited abstract method com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.getOid()
[ERROR] The type app.domain.model.Generation must implement the inherited abstract method com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.getVersion()
[ERROR] The type app.domain.model.Generation must implement the inherited abstract method com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I.setVersion(J)
[ERROR] The type app.domain.model.Generation must implement the inherited abstract method com.scispike.foundation.domain.trait.interfaces.persistence.Persistable.getOid()
[ERROR] The type app.domain.model.Generation must implement the inherited abstract method com.scispike.foundation.domain.trait.interfaces.persistence.Persistable.getVersion()
Comment 11 Andrew Clement CLA 2012-10-02 13:55:41 EDT
'must implement' is a bit different to the AbstractMethodError. I have tinkered in this area a little during the 1.7.0>1.7.1 timeframe to fix some spring data issues.

Yes, it is very different if applying aspects later than applying them up front - as either the compiler or the weaver will be in charge of checking things like whether all necessary methods have been implemented in a hierarchy. If it works as a full source build but fails when separate then that indicates the weaver is not behaving.

I'll get to it when I can but can't promise it'll be this week.
Comment 12 Matthew Adams CLA 2012-10-03 10:03:10 EDT
(In reply to comment #10)
> up in project foundation/domain, no compilation errors are not
> present.
> 
Should've said "no compilation errors are present"...oops.
Comment 13 Matthew Adams CLA 2012-10-05 11:08:36 EDT
(In reply to comment #11)
> I'll get to it when I can but can't promise it'll be this week.

When you do, use commit f59244f7c0b33ff728ed1b732e1aee2721966c88 on the feature/test-persistence-trait branch.  That's the one where I was seeing the error.
Comment 14 Matthew Adams CLA 2012-11-28 09:35:34 EST
[bump] Any progress on this one yet?
Comment 15 Andrew Clement CLA 2012-12-11 17:17:15 EST
I switched to the commit you referenced and run 'mvn clean compile' - that all works. From the last few comments I can't quite see what to run to see the failure? I tried just building foundation/test-client/mongo/domain but that didn't fail either. I presume I don't have to import it into ajdt to see the problem and I should just be seeing it with maven?
Comment 16 Matthew Adams CLA 2012-12-11 17:59:02 EST
Oy vey.  I just tried to repro using that commit, too, and I'm getting a different error.  I'm going to have look deeper into repro steps and get back to you, which I can't do tonight.  Hang tight.
Comment 17 Matthew Adams CLA 2012-12-12 10:30:58 EST
Ok, I can reproduce the errors now.  I'm getting the "must implement the inherited abstract method" errors in the foundation/domain project, but only when building the project from the root level.  After working around that, I can repro the build errors in the foundation/test-client/mongo part of the project.  Read on.

Here's what I did:

$ git checkout -b ajc-bug f59244f7c0b33ff728ed1b732e1aee2721966c88
$ git status
# On branch ajc-bug
nothing to commit (working directory clean)


Now, ensure pwd is $GIT_REPO/foundation, where $GIT_REPO is the root dir of the git repo.

$ cd foundation
$ mvn clean install
...
[ERROR] Failed to execute goal org.codehaus.mojo:aspectj-maven-plugin:1.4:test-compile (default-testCompile) on project foundation-domain: Compiler errors:
[ERROR] error at public class JpaLongPerson {
[ERROR] ^^^^^^^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/domain/src/test/java/com/scispike/foundation/domain/test/unit/aspectj/persistence/jpa/JpaLongPerson.java:8:0::0 The type JpaLongPerson must implement the inherited abstract method PersistableAspect.I<Long>.setVersion(long)
[ERROR] error at public class JpaLongPerson {
...


Now, I workaround that problem.  If I change to the domain directory, then build again, the domain project builds ok.  That's one thing that needs to be fixed.

$ cd domain
$ mvn clean install
...
[INFO] Installing /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/domain/pom.xml to /Users/matthew/.m2/repository/com/scispike/foundation-domain/0.1.0.BUILD-SNAPSHOT/foundation-domain-0.1.0.BUILD-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.575s
[INFO] Finished at: Wed Dec 12 09:23:19 CST 2012
[INFO] Final Memory: 12M/81M
[INFO] ------------------------------------------------------------------------


Next, I change to the foundation/test-client/mongo dir and can repro the build errors:

$ cd ../test-client/mongo
$ mvn clean install
...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO] 
[INFO] Foundation: Mongo Test Support
[INFO] Foundation: Mongo Domain Test
[INFO] Foundation: Mongo Test Root
...
[INFO] ------------------------------------------------------------------------
[INFO] Building Foundation: Mongo Domain Test 0.1.0.BUILD-SNAPSHOT
[INFO] ------------------------------------------------------------------------
...
[INFO] --- aspectj-maven-plugin:1.4:compile (default-compile) @ foundation-mongo-domain-test ---
[WARNING] this affected type is not exposed to the weaver: com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo [Xlint:typeNotExposedToWeaver]
[WARNING] this affected type is not exposed to the weaver: com.scispike.foundation.domain.aspectj.trait.persistence.PersistableMongoAspect$StringMongo [Xlint:typeNotExposedToWeaver]
[WARNING] this affected type is not exposed to the weaver: com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$S [Xlint:typeNotExposedToWeaver]
[WARNING] this affected type is not exposed to the weaver: com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$S [Xlint:typeNotExposedToWeaver]
[WARNING] this affected type is not exposed to the weaver: com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I [Xlint:typeNotExposedToWeaver]
[WARNING] this affected type is not exposed to the weaver: com.scispike.foundation.domain.aspectj.trait.persistence.PersistableAspect$I [Xlint:typeNotExposedToWeaver]
[ERROR] The type Address must implement the inherited abstract method PersistableAspect.I<String>.setVersion(long)
[ERROR] The type Address must implement the inherited abstract method PersistableAspect.I<String>.getOid()
[ERROR] The type Address must implement the inherited abstract method PersistableAspect.I<String>.equals(Persistable<?>)
[ERROR] The type Address must implement the inherited abstract method PersistableAspect.I<String>.getVersion()
[ERROR] The type Generation must implement the inherited abstract method PersistableAspect.I<String>.setVersion(long)
[ERROR] The type Generation must implement the inherited abstract method PersistableAspect.I<String>.getOid()
[ERROR] The type Generation must implement the inherited abstract method PersistableAspect.I<String>.equals(Persistable<?>)
[ERROR] The type Generation must implement the inherited abstract method PersistableAspect.I<String>.getVersion()
[ERROR] The type Person must implement the inherited abstract method PersistableAspect.I<String>.setVersion(long)
[ERROR] The type Person must implement the inherited abstract method PersistableAspect.I<String>.getOid()
[ERROR] The type Person must implement the inherited abstract method PersistableAspect.I<String>.equals(Persistable<?>)
[ERROR] The type Person must implement the inherited abstract method PersistableAspect.I<String>.getVersion()
[ERROR] The type User must implement the inherited abstract method PersistableAspect.I<String>.setVersion(long)
[ERROR] The type User must implement the inherited abstract method PersistableAspect.I<String>.getOid()
[ERROR] The type User must implement the inherited abstract method PersistableAspect.I<String>.equals(Persistable<?>)
[ERROR] The type User must implement the inherited abstract method PersistableAspect.I<String>.getVersion()
[WARNING] advice defined in org.springframework.orm.jpa.aspectj.JpaExceptionTranslatorAspect has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in org.springframework.mock.staticmock.AnnotationDrivenStaticEntityMockingControl has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in org.springframework.mock.staticmock.AbstractMethodMockingControl has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in org.springframework.mock.staticmock.AbstractMethodMockingControl has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in com.scispike.foundation.domain.aspectj.validation.ApacheBvalMethodValidationAspect has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in com.scispike.foundation.domain.aspectj.validation.ApacheBvalMethodValidationAspect has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in com.scispike.foundation.domain.aspectj.validation.ApacheBvalMethodValidationAspect has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in org.springframework.scheduling.aspectj.AbstractAsyncExecutionAspect has not been applied [Xlint:adviceDidNotMatch]
[WARNING] advice defined in com.scispike.foundation.domain.aspectj.trait.logging.LoggableAspect has not been applied [Xlint:adviceDidNotMatch]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO] 
[INFO] Foundation: Mongo Test Support .................... SUCCESS [2.328s]
[INFO] Foundation: Mongo Domain Test ..................... FAILURE [1.292s]
[INFO] Foundation: Mongo Test Root ....................... SKIPPED
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3.796s
[INFO] Finished at: Wed Dec 12 09:24:48 CST 2012
[INFO] Final Memory: 12M/81M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:aspectj-maven-plugin:1.4:compile (default-compile) on project foundation-mongo-domain-test: Compiler errors:
[ERROR] error at public final class Address {
[ERROR] ^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Address.java:8:0::0 The type Address must implement the inherited abstract method PersistableAspect.I<String>.setVersion(long)
[ERROR] error at public final class Address {
[ERROR] ^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Address.java:8:0::0 The type Address must implement the inherited abstract method PersistableAspect.I<String>.getOid()
[ERROR] error at public final class Address {
[ERROR] ^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Address.java:8:0::0 The type Address must implement the inherited abstract method PersistableAspect.I<String>.equals(Persistable<?>)
[ERROR] error at public final class Address {
[ERROR] ^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Address.java:8:0::0 The type Address must implement the inherited abstract method PersistableAspect.I<String>.getVersion()
[ERROR] error at public final class Generation {
[ERROR] ^^^^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Generation.java:11:0::0 The type Generation must implement the inherited abstract method PersistableAspect.I<String>.setVersion(long)
[ERROR] error at public final class Generation {
[ERROR] ^^^^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Generation.java:11:0::0 The type Generation must implement the inherited abstract method PersistableAspect.I<String>.getOid()
[ERROR] error at public final class Generation {
[ERROR] ^^^^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Generation.java:11:0::0 The type Generation must implement the inherited abstract method PersistableAspect.I<String>.equals(Persistable<?>)
[ERROR] error at public final class Generation {
[ERROR] ^^^^^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Generation.java:11:0::0 The type Generation must implement the inherited abstract method PersistableAspect.I<String>.getVersion()
[ERROR] error at public final class Person {
[ERROR] ^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Person.java:15:0::0 The type Person must implement the inherited abstract method PersistableAspect.I<String>.setVersion(long)
[ERROR] error at public final class Person {
[ERROR] ^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Person.java:15:0::0 The type Person must implement the inherited abstract method PersistableAspect.I<String>.getOid()
[ERROR] error at public final class Person {
[ERROR] ^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Person.java:15:0::0 The type Person must implement the inherited abstract method PersistableAspect.I<String>.equals(Persistable<?>)
[ERROR] error at public final class Person {
[ERROR] ^^^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/Person.java:15:0::0 The type Person must implement the inherited abstract method PersistableAspect.I<String>.getVersion()
[ERROR] error at public final class User {
[ERROR] ^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/User.java:16:0::0 The type User must implement the inherited abstract method PersistableAspect.I<String>.setVersion(long)
[ERROR] error at public final class User {
[ERROR] ^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/User.java:16:0::0 The type User must implement the inherited abstract method PersistableAspect.I<String>.getOid()
[ERROR] error at public final class User {
[ERROR] ^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/User.java:16:0::0 The type User must implement the inherited abstract method PersistableAspect.I<String>.equals(Persistable<?>)
[ERROR] error at public final class User {
[ERROR] ^^^
[ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/test-client/mongo/domain/src/main/java/app/domain/model/User.java:16:0::0 The type User must implement the inherited abstract method PersistableAspect.I<String>.getVersion()
[ERROR] -> [Help 1]
[ERROR] 
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR] 
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException
[ERROR] 
[ERROR] After correcting the problems, you can resume the build with the command
[ERROR]   mvn <goals> -rf :foundation-mongo-domain-test

That's the error I was getting before.  Let me know if you have any trouble reproducing this error.
Comment 18 Andrew Clement CLA 2012-12-14 16:46:51 EST
So you seem to have multiple issues there? I'd like to take them one at a time.

I'm trying to follow these instructions below. I assume the 'cd foundation' is redundant if I have ensured my pwd is $GET_REPO/foundation.

> $ git checkout -b ajc-bug f59244f7c0b33ff728ed1b732e1aee2721966c88
> $ git status
> # On branch ajc-bug
> nothing to commit (working directory clean)
>
> Now, ensure pwd is $GIT_REPO/foundation, where $GIT_REPO is the root dir of
>  the git repo.
>
> $ cd foundation
> $ mvn clean install
> ...
> [ERROR] Failed to execute goal org.codehaus.mojo:aspectj-maven-plugin:1.4:test-compile (default-testCompile) on project foundation-domain: Compiler errors:
> [ERROR] error at public class JpaLongPerson {
> [ERROR] ^^^^^^^^^^^^
> [ERROR] /Users/matthew/Documents/bitbucket/scispike-foundation/foundation/domain/src/test/java/com/scispike/foundation/domain/test/unit/aspectj/persistence/jpa/JpaLongPerson.java:8:0::0 The type JpaLongPerson must implement the inherited abstract method PersistableAspect.I<Long>.setVersion(long)
> [ERROR] error at public class JpaLongPerson {

When I run 'mvn clean install' I don't get any compilation errors, I just see a test failure:


Running TestSuite
Configuring TestNG with: org.apache.maven.surefire.testng.conf.TestNGMapConfigurator@71429c57
Tests run: 3, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.523 sec <<< FAILURE!

Results :

Failed tests:   testAllLocales(com.scispike.foundation.test.unit.i18n.LocaleStringConverterTest): (..)

Tests run: 3, Failures: 1, Errors: 0, Skipped: 0

The difference suggests something being important about the ordering of the files passed to the compiler.
Comment 19 Andrew Clement CLA 2012-12-14 16:54:05 EST
I then cd'd into domain and tried 'mvn clean install' there:

[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 6.051s
[INFO] Finished at: Fri Dec 14 13:52:52 PST 2012
[INFO] Final Memory: 15M/214M
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:aspectj-maven-plugin:1.4:compile (default-compile) on project foundation-domain: Compiler errors:
[ERROR] error at import com.scispike.foundation.scope.aspectj.AbstractInternalAspect;
[ERROR] ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[ERROR] /Users/aclement/gits/matthew/scispike-foundation/foundation/domain/src/main/aspect/com/scispike/foundation/domain/aspectj/scope/InternalAspect.aj:3:0::0 The import com.scispike.foundation.scope.aspectj cannot be resolved
[ERROR] error at public aspect InternalAspect extends AbstractInternalAspect {
[ERROR] ^^^^^^^^^^^^^^^^^^^^^
[ERROR] /Users/aclement/gits/matthew/scispike-foundation/foundation/domain/src/main/aspect/com/scispike/foundation/domain/aspectj/scope/InternalAspect.aj:5:0::0 AbstractInternalAspect cannot be resolved to a type
[ERROR] -> [Help 1]
Comment 20 Matthew Adams CLA 2012-12-14 18:29:41 EST
For anyone listening, the inability to repro was due to the use of JDK 1.7 versus 1.6.  1.6 should've been used; there is (yet another) error when compiling with 1.7.
Comment 21 Andrew Clement CLA 2013-01-23 21:03:05 EST
Ok, spent time on this today, very tricky.  Even though I have reproduced it, it doesn't happen everytime which makes debugging it hard (also attaching the debugger reduces the frequency with which it fails).

I believe the problem here is that the ITDs look like they don't apply because types like Generation don't appear to implement PersistableAspect$I.  This isn't true but what is happening is that there are two representations of the 'PersistableAspect$I' generic type around during the failing case and as the check is '==' then we fail to add the ITD (and so get the 'must implement' message). This, coupled with the fact that it doesn't happen all the time, suggests to me it is related to type demotion in some way.  The typemap should only contain one representation of the generic type and everything should be using that one. It is feasible, I guess, that demotion threw something out before it was finished with, causing a second different variant to be created.

I'll need to build a patched version of AspectJ with extra debug in to verify a few things like what happens if type demotion is turned off.
Comment 22 Matthew Adams CLA 2013-01-24 18:44:38 EST
Wow.  Ok, I think I'll take your word on this.  Sounds scary for someone who's not familiar with the codebase.
Comment 23 Andrew Clement CLA 2013-01-25 16:47:18 EST
Think I got it, holy hell it was hard to get to the bottom of it.

AspectJ has a typemap that maps signatures to type objects.  For generic types this typemap holds the raw type objects and they have a pointer internally to their generic type object.  The objects are held by weak reference so if no-one is using them, they are GC'd.

In this situation we couldn't apply an ITD because we were comparing two generic types that were different. In fact they were for the same signature but as they failed the == test they were considered different.  The type map should ensure that everyone uses the same type for the same signature.

The problem that was occurring was that sometime after the typemap entry is built for the marker interface (PersistableAspect$I), an itd was resolving its target type. It determined it to be PersistableAspect$I and as ITDs apply to the generic form, it held onto a reference to the generic form.

*This left no references to the raw form*, thus it was a candidate for GC, and when GC'd the reference to the generic type through the typemap was 'lost' (although it was still around in memory).

We then come across the name PersistableAspect$I again and build a new typemap entry with a *new* backing generic type (because we couldn't find the old one).

Then when looking at whether the ITD applies to a type sometime later we end up comparing the generic type from the resolved ITD with the generic type built later and that fails.

As WeakReferences were in use, you are at the mercy of the JVM as to when the generic type will be isolated - that is why it happens only some of the time. (at least in my experience).

I've now enabled generic types to have a reference back to their raw variant. This ensures whilst the generic is in use, the raw cannot be a GC candidate.

Built a new snapshot and now the code all builds fine every time.
Comment 24 Andrew Clement CLA 2013-01-25 20:04:32 EST
Fix committed, available as 1.7.2.BUILD-SNAPSHOT in usual maven repo.

It also seems to fix the early compile weirdness when doing 'mvn clean install' in foundation (at least that doesn't fail for me anymore).

Sorry I took so long to fix it.