AspectJ does not weave JUnit classes when built with Ant - java

I have created an aspect with AspectJ, to build it and weave my classes during compile time with it I use ANT task. I have also created test class that is intended to test how that aspect works. Here is the problem: my test classes are not being weaved. And I do not why.
My source folder is src/main/java and my test folder is src/test/java
When I move my test class to the source folder everything works fine..
Update 1: I am not using AspectJ in conjunction with Spring. Also I am not using aop.xml, my aspects are being annotated.
Update 2: my ant compile-aspectj-tests target looks like this:
<target name="compile-aspectj-tests" depends="compile">
<taskdef resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
<classpath>
<pathelement location="${ivy.install.dir}/../cache/org.aspectj/aspectjtools/jars/aspectjtools-1.7.3.jar" />
</classpath>
</taskdef>
<iajc srcDir="${test.dir}/java" destDir="${compiled.tests}" debug="on" Xlintwarnings="true"
showWeaveInfo="true" source="${targetVersion}" target="${targetVersion}" >
<classpath>
<path refid="test.classpath" />
<pathelement location="${compiled.src}" />
</classpath>
<aspectpath location="${compiled.src}" />
</iajc>
</target>
This is what I see in the console:
compile-aspectj-tests:
[iajc] warning at com/.../cache/aspects/RetryJedisConnectionExceptionAspect.java::0 no match for this type name: RetryJedisConnectionException [Xlint:invalidAbsoluteTypeName]
Any help would be appreciated.

Related

Why do we set classpath in ant

Below is the code for setting class path in ant.
<path id="build.classpath">
<fileset dir="${lib.dir}">
<include name="**/*.jar" />
</fileset>
</path>
<target name="compile" depends="clean">
<javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="build.classpath" />
</target>
Why do we need to set classpath in ant ?
Think of ant as a framework to run your build tasks - compiling the code, running the (unit) tests, etc. In order to properly compile and execute your (test) code, java will need access to the third party libraries you may be using (e.g., JUnit for running unit tests). The classpath tells java where these JARs are located, so it can use them.

How to compile the annotation processor with Ant?

The question seems to be obvious, but the implementation is pretty hard for me.
My goal is to write Ant build script to compile some classes that require another classes generated by Annotation Processor.
I have a custom annotations and it's processor implementation (inherited from AbstractProcessor class).
As I understand I need to:
Compile the Annotation Processor
Run the compiler over some annotated classes to generate the new ones.
Compile the classes that require generated classes
The code (step 1 & 2):
<target name="compileAnnotationProcessor">
<javac destdir="${OUTPUT_DIR}"
debug="true"
failonerror="true"
includeantruntime="false"
classpath="${java.class.path}">
<src>
<pathelement path="${PROJECT_DIR}/tools/src"/>
</src>
<include name="/path/to/annotation/processor/package/**"/>
</javac>
</target>
<target name="generateFilesWithAPT" depends="compileAnnotationProcessor">
<javac destdir="${OUTPUT_DIR}"
includeantruntime="false"
listfiles="false"
fork="true"
debug="true"
verbose="true">
<src>
<pathelement path="${PROJECT_DIR}/common/src/"/>
</src>
<include name="/path/to/files/to/compile/**"/>
<classpath>
<pathelement path="${OUTPUT_DIR}"/>
<pathelement path="${java.class.path}"/>
</classpath>
<compilerarg line="-proc:only"/>
<compilerarg line="-processorpath ${OUTPUT_DIR}/path/to/annotation/processor/package/annProcessorImplement"/>
</javac>
</target>
Actually, the first task is performing good and compiles the .class file for the Annotation processor implementation. It is stopping at 2nd task.
Ant says: Annotation processing without compilation requested but no processors were found.
What am I doing wrong?
Maybe I should put the annotation processor class in a .jar? Or provide a file name with .class extension as -processorpath argument?
I tried several options but nothing helps..
Notes:
I'm using ant javac task instead of aptone because documentation claims that apt tool as well as com.sun.mirror API is deprecated.
I've also looked through this question, but there is no information how to compile the processor in right way.
I'm using:
Java 1.6
Ant 1.8.2
My usual approach is:
pack the annotation together with the annotation processor in its own jar
register the annotation processor via META-INF/services in that jar
Then wherever you have a dependency on your annotations, the annotation processor will be picked up automatically without any additional configuration.

Compile GWT project with GWT project dependencies

I'd love to ask about my issue with ant script. I have two GWT projects and one depends on the other. I'm trying to compile them with ant script, but I'm failing due to:
[java] [ERROR] Errors in 'file:/$PATH/$CLASS_NAME.java'
[java] [ERROR] Line 29: No source code is available for type $INHERITED_INTERFACE; did you forget to inherit a required module?
while $INERITED_INTERFACE is from the library the compiled project depends on and $CLASS_NAME is a class that implements the interface.
I tried it simple, but it's not working:
<target name="gwtcomp" depends="javacomp" description="GWT to JS">
<echo message="Building GWT" />
<java failonerror="true" fork="true" classname="com.google.gwt.dev.Compiler">
<classpath>
<pathelement location="${basedir}/src" />
<path refid="project.class.path" />
</classpath>
<jvmarg value="-Xmx512M" />
<arg value="-strict" />
<arg value="${project.dep.gwt.config}" />
<arg value="${project.gwt.config}" />
</java>
</target>
but it can't go pass the errors. I've also inherited the GWT library with:
<module rename-to='project'>
...
<inherits name='my.lib.common.Common'/>
</module>
Not really sure what's wrong. Common.gwt.xml is there and it points client and shared as source packages. Could anyone help with that?
I guess you have to add the location for the sources of your my.lib.common.Common library to your classpath in your ant script.
Something like this:
<classpath>
<pathelement location="${basedir}/src" />
<path refid="project.class.path" />
<pathelement location="LOCATION_TO_MY.LIB.COMMON.COMMON"/>
</classpath>

AspectJ (annotations) compile-time weave with Ant and NetBeans

I want to use compile-time AspectJ with Ant in NetBeans. I want to run it on Google App Engine, but it is not essential at the moment. AspectJ is annotation based.
I prefer compile-time weave (modification, instrumentation? of classes). I wouldn't like to use a custom classloader. How to achieve this?
What I already have:
I tried AspectJ Annotation Tutorial with NetBeans. I modified build.xml to process aspectj (using iajc Ant task) as described here. The problem is that it requires adding -javaagent:lib/aspectjweaver.jar (it is not possible on GAE).
Running my build generates this output:
info compiling C:\NetBeansProjects\TryAspectJ\src\net\andrewewhite\examples\HelloWorld.java
weaveinfo Join point 'method-call(void java.io.PrintStream.println(java.lang.String))' in Type 'net.andrewewhite.examples.HelloWorld' (HelloWorld.java:9) advised by before advice from 'net.andrewewhite.aspects.BasicAspect' (BasicAspect.class:17(from BasicAspect.java))
weaveinfo Join point 'method-call(void java.io.PrintStream.println(java.lang.String))' in Type 'net.andrewewhite.examples.HelloWorld' (HelloWorld.java:9) advised by after advice from 'net.andrewewhite.aspects.BasicAspect' (BasicAspect.class:23(from BasicAspect.java))
info woven class net.andrewewhite.examples.HelloWorld (from C:\NetBeansProjects\TryAspectJ\src\net\andrewewhite\examples\HelloWorld.java)
info Compiler took 2547ms
When I run my project with -javaagent parameter it works OK. (In NetBeans: Click on project>Properties>Run>VM Options: -javaagent:./dist/lib/aspectjweaver.jar). Otput for code from tutorial:
run:
About to make call to print Hello World
Hello World!
Just made call to print Hello World
BUILD SUCCESSFUL (total time: 0 seconds)
Without agent (VM Options cleared) code runs as if it was without AspectJ:
run:
Hello World!
BUILD SUCCESSFUL (total time: 0 seconds)
Sources:
\TryAspectJ\src\META-INF\aop.xml
<?xml version="1.0" encoding="UTF-8"?>
<aspectj>
<aspects>
<aspect name="net.andrewewhite.aspects.BasicAspect" />
</aspects>
</aspectj>
\TryAspectJ\src\net\andrewewhite\aspects\BasicAspect.java
package net.andrewewhite.aspects;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
#Aspect
public class BasicAspect {
#Before(" call(void java.io.PrintStream.println(java.lang.String)) " +
"&& !within(net.andrewewhite.aspects..*)")
public void beforePrintlnCall() {
System.out.println("About to make call to print Hello World");
}
#After(" call(void java.io.PrintStream.println(java.lang.String)) " +
"&& !within(net.andrewewhite.aspects..*)")
public void afterPrintlnCall() {
System.out.println("Just made call to print Hello World");
}
}
\TryAspectJ\src\net\andrewewhite\examples\HelloWorld.java
package net.andrewewhite.examples;
public class HelloWorld {
public static void main(String[] argv) {
System.out.println("Hello World!");
}
}
\TryAspectJ\build.xml
<?xml version="1.0" encoding="UTF-8"?>
<project name="TryAspectJ" default="default" basedir=".">
<description>Builds, tests, and runs the project TryAspectJ.</description>
<import file="nbproject/build-impl.xml"/>
<taskdef classpath="lib/aspectj/aspectjtools.jar" resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"/>
<target name="aspectj">
<echo level="info">--- aspectj (start) ---</echo>
<iajc destDir="${build.classes.dir}" source="1.6" target="1.6" showweaveinfo="true" verbose="true" >
<inpath>
<pathelement location="lib/aspectj/aspectjrt.jar"/>
<pathelement location="${build.classes.dir}" />
</inpath>
<sourceroots>
<pathelement location="${src.dir}"/>
</sourceroots>
<classpath>
<pathelement location="${javac.classpath}"/>
<pathelement location="${j2ee.platform.classpath}"/>
</classpath>
</iajc>
 <echo level="info">--- aspectj finished ---</echo>
</target>
<target name="-post-compile" depends="aspectj"></target>
</project>
What do I have to add or change?
Found solution.
This is the correct build.xml fragment:
<taskdef classpath="lib/aspectjtools.jar" resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"/>
<target name="aspectj">
<echo level="info">--- aspectj (start) ---</echo>
<!-- begin fix classpath for this bug https://issues.apache.org/bugzilla/show_bug.cgi?id=40291 -->
<condition property="targetos" value="windows" else="unix">
<os family="windows"/>
</condition>
<!-- converting classpath -->
<pathconvert targetos="${targetos}" property="javac.convertedClasspath" >
<path path="${javac.classpath}" />
</pathconvert>
<!-- end fix classpath -->
<iajc source="1.6" target="1.6" showweaveinfo="true" verbose="true" destdir="${build.classes.dir}" >
<inpath>
<pathelement location="${build.classes.dir}"/>
</inpath>
<classpath>
<pathelement location="${javac.convertedClasspath}" />
</classpath>
</iajc>
<echo level="info">--- aspectj (finished) ---</echo>
</target>
<target name="-post-compile" depends="aspectj"></target>
Calling java -classpath ./lib/aspectjrt.jar -jar TryAspectJ.jar works OK. What is strange is that from NetBeans (Right clik on project->Run) results are as if they were without AspectJ. I think that NetBeans runs projects from build/classes dir not as jar. But it's not a problem.
You need to add an aspect path element as a subelement to the iajc element.
<aspectpath>
<pathelement location="..." />
</aspectpath>
The aop.xml file is only necessary for AspectJ load-time weaving.

How can I build my jar file so that users who use the library will be able to see the javadoc in Eclipse

I'm working on a small library for our in-company use, and have been heavily documenting it. Now I'm building my jar with the following code:
<project name="commonutils" default="compile" basedir=".">
<property name="src" location="src" />
<property name="build" location="buildDirecotry" />
<target name="compile">
<delete file="${ant.project.name}.jar" />
<mkdir dir="${build}"/>
<javac srcdir="${src}" destdir="${build}" debug="on" target="1.5">
<classpath>
<pathelement location="lib/build/server.zip" />
<pathelement path="${java.class.path}/"/>
</classpath>
</javac>
<jar basedir="${build}" destfile="${ant.project.name}.jar" />
<delete dir="${build}" />
</target>
</project>
Which works fine, it builds my jar file with all the src files in it, but when I include the jar file in another project I no-longer have any of my javadoc comments. Using JDDecompiler I cannot see the comments in the class file, although I'm not sure if its the java compiler that's stripping them or JD.
My question is: How can I build my jar file so that users who use the library will be able to see the javadoc in Eclipse.
If you include the source files in the jar (each class and java file in the same package-directory) it should work.
<target name="jar.noCompile.src">
<jar destfile="${ant.project.name}.jar">
<fileset dir="${build}"/>
<fileset dir="${src}" includes="**/*.java"/>
</jar>
</target>
AFAIK the documentation is an Eclipse feature. You have to configure it manually. In your build generate the documentation (usually into folder 'javadoc') and package it with the JAR. Once someone wants to use your library, he/she has to go into Java Build Path select libraries, add yours, click next to it to open the tree node and then double click on Javadoc location to configure it.

Categories

Resources