I'm sure this amounts to Newbie question for AspectJ but reviewing books and web sites, I'm not seeing the answer in terms I recognize.
Summary: In my Client Jar, I am getting compilation errors complaining that methods that were added as a part of "Aspect B" are not present.
I have a setup similar to :
+---------------------+
| |
| Client Jar |
| |
+--+---------------+--+
| |
| |
+----------+----+ +-------v-------+
| JSON Serial / | | Other Aspect |
| Deser Aspect | +---------------+
+-------------+-+ +-------v-------+
| | Potential |
| | Other Jar |
| +---------------+
|
+----v-----------+
| Javabean |
| Aspects |
+----------------+
+----v-----------+
| Basic Data |
| Objects |
+----------------+
Essentially, I have two levels of aspects where behaviors are being extended in each layer.
Assume the following class in "Basic Data Objects":
BasicDataObjects SampleObject
public class SampleObject {
private String name;
private int age;
}
and the following aspect in JavaBean Aspects:
privileged aspect SampleObject_JavaBean {
public String SampleObject.getName() {
return this.name;
}
}
And the following aspect in JSON Aspects:
privileged aspect SampleObject_Json {
public String SampleObject.getNameValue() {
return this.name == null ? null : this.name.serialize();
}
}
Finally, in the actual client jar, I am getting the following as a compilation error:
public void someMethod (SampleObject obj) {
obj.getNameValue() // <-- This has a compilation error that the getNameValue() is unresolvable.
}
In my Client Jar, I am getting compilation errors that methods that were added as a part of "Aspect B" are not available.
My expectation was that the "Aspect A" generated jar file should have all its own classes compiled as well as all the classes that were provided as a part of "Aspect B".
Aspect B pom:
<project>
<!-- (...) -->
<artifactId>aspect-b</artifactId>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-data-objects</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<complianceLevel>${java.version}</complianceLevel>
<source>${java.version}</source>
<target>${java.version}</target>
<weaveDependencies>
<weaveDependency>
<groupId>com.example</groupId>
<artifactId>lib-data-objects</artifactId>
</weaveDependency>
</weaveDependencies>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
<!-- (...) -->
</project>
Aspect A pom:
<project>
<!-- (...) -->
<artifactId>aspect-a</artifactId>
<dependencies>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>${aspectj.version}</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>lib-data-objects</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>aspect-b</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<complianceLevel>${java.version}</complianceLevel>
<source>${java.version}</source>
<target>${java.version}</target>
<weaveDependencies>
<weaveDependency>
<groupId>com.example</groupId>
<artifactId>aspect-b</artifactId>
</weaveDependency>
</weaveDependencies>
</configuration>
</plugin>
</plugins>
</build>
<!-- (...) -->
</project>
Client Jar pom:
<project>
<!-- (...) -->
<dependencies>
<dependency>
<groupId>com.example</groupId>
<artifactId>aspect-a-wrapper</artifactId>
<version>${aspect-a.version}</version>
</dependency>
<groupId>com.example</groupId>
<artifactId>lib-data-objects</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.7</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<outxml>true</outxml>
<complianceLevel>${java.version}</complianceLevel>
<source>${java.version}</source>
<target>${java.version}</target>
<weaveDependencies>
<weaveDependency>
<groupId>com.example</groupId>
<artifactId>aspect-a</artifactId>
</weaveDependency>
</weaveDependencies>
</configuration>
</plugin>
</plugins>
</build>
<!-- (...) -->
</project>
As you said in your own answer, in your client JAR pom.xml you have defined dependencies on both
But you only need the latter, so you should remove the former.
That you use weaveDependencies in your aspect libraries is okay and necessary because otherwise they will not compile in your scenario: Aspect B needs the data objects library because otherwise it cannot find the classes it should add new methods to. Aspect B needs Aspect A because it wants to use an already aspect-enhanced library to add even more methods via ITD. I don't think that this is a particularly nice setup because Aspect B needs to know about Aspect A, which creates an unnecessary transitive dependency ClientJar -> AspB -> AspA -> DataObj
. Maybe it would be wiser to aspect-enhance the data objects library directly and shorten the chain to ClientJar -> DataObj
. This is only bad if you really need the plain library without any added ITD methods in other circumstances. Then you could still create a plain and a fully aspect-enhanced version (only one stage of aspect enhancement, not two transitively dependent ones).
Update, 2015-01-02:
I had some leftover time and have started looking into this again. What I have ended up with is a nice solution (see GitHub repo) with the following characteristics:
<weaveDependency>
, section <weaveDependencies>
.<aspectLibrary>
, section <aspectLibraries>
.<aspectLibrary>
(even though it does not contain any aspects, don't be confused by the naming). This effectively avoids any woven core classes from being part of aspect libraries. It would not be useful to have multiple versions of woven core classes with mutually exclusive aspects in the aspect library because which one should win in the end? We need a version of our core code with all aspect libraries woven in at the same time, or at least all we choose to configure in another module.<weaveDependencies>
this time, because all of them should be in the resulting JAR. In order to enable binary weaving in the AspectJ Maven plugin, we need to add one dummy class because the plugin does not compile or weave anything if it does not find any source files in its own module. The dummy class is stripped from the output again via an explicit exclusion configured in the Maven JAR plugin. The exclusion is nice to have, you could also just ignore the dummy class in the output JAR.main
method to the whole mix in order to make it runnable and testable from the command line. The driver application uses getter methods created by both the JSON and the Java Beans aspects in order to prove that they really exist and are functional.java -jar client-jar/target/client-jar-1.0-SNAPSHOT.one-jar.jar
mvn --projects client-jar exec:exec
. This is also nice to have, just like the über-JAR itself, but why make life harder than necessary? ;-)Console in-/output:
$ java -jar client-jar/target/client-jar-1.0-SNAPSHOT.one-jar.jar
SampleObject{name='John Doe', age=33}
Java Bean properties:
John Doe
33
JSON properties:
"Name" : "John Doe"
"Age" : 33
Update, 2015-01-03:
I added the capability to create a custom mix of aspects applied to your core code during weaving in module data-objects-aspectj by means of Maven profiles, see changeset 32ee5fc.