views:

189

answers:

2

At my work we use AspectJ in some of our Java projects. To get this to work with ant builds we have been placing aspectjtools.jar within ant/lib/.

I am now working on a particular Java project and need to use a newer version of aspectJ. I don't want to have to get everyone who uses the project to update their local copy of aspectjtools.jar. Instead, I tried adding the newer aspectjtools.jar to the lib directory of the project and adding the following line to build.xml.

  <taskdef
     resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties"
     classpath="./lib/aspectjtools.jar" />

However, this doesn't work as I hoped as the ANT classloader loads jars from ant/lib/ in preference to the jar I specify in the taskdef classpath.

Is there any way to force ant to pick the jar checked into my project instead?

+3  A: 

Hello, can't you just update the iajc compile target to use the new jar on the classpath?

It's not possible to force the classloader to prefer a given jar file over another one. If you must relate to several version of the same class, then you should consider OSGI.

The simplest solution will be to just use libraries from the project or a Maven/Ivy repository and ignore the libraries in your global ant folder.

An example:

 <taskdef 
     resource="org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties">
      <classpath>
         <pathelement location="${basedir.dir}/lib/aspectjtools.jar"/>
      </classpath>
 </taskdef>

 <target name="compile" >
    <iajc outjar="demo.jar">
        <sourceroots>
            <pathelement location=”src” />
        </sourceroots>
        <aspectpath>
            <pathelement 
              location="aspects_to_be_weaved_with_classes_in_sourceroots.jar" />
        </aspectpath>
        <classpath>
            <pathelement location="${basedir}/lib/aspectjrt.jar"/>
        </classpath>
    </iajc>
  </target>

Updated: You also have to use another Ant. If you're using Eclipse, try the bundled one directly from the Ant view.

You also have another option, but it's a little bit more difficult. That is to use AspectJ load-time weaving instead. If you go for that option, you can compile with an ordinary compile task, but you have to do the weaving with an JVM agent at startup. You can read more about it here.

I hope this helps!

Espen
Thanks for the answer. I will test whether this works tomorrow.
mchr
This doesn't solve my problem. The taskdef element allows you to specify a classpath but my testing shows this classpath is inserted at the end of the existing classpath. This means ANT will always use aspectjtools.jar in the ant/lib/ directory in preference to any version specified in the taskdef classpath.
mchr
Thanks for the update - I can see that using another copy of ant would solve my problem but only by sidestepping the issue.The load time weaving is another valid solution but feels particularly overcomplicated.Is it really so unreasonable for ANT to provide a mechanism for a project to force which version of a task is used?
mchr
If I understand you correct, it's not Ant that's the problem, but how classloaders work in Java. You can get the same problem if you have an old version of a lib in the web container's lib folder and you want to override one of those classes with a class from a lib in your war file. Try to use another version of Ant without the aspectjtools.jar in ant's lib folder, but only on the project's classpath.
Espen
There is nothing inherant in the way classloaders work that causes this behaviour. I would expect ant to implement the <classpath> element as a nested classloader which would only delegate to ant if it could not find a class. This would allow a project to override classes in ant/lib/. I will propose this to the ant devs.
mchr
+1  A: 

The ultimate answer to my question is no. The is currently no way for ANT to use a task jar from a project in preference to a task jar in the ANT lib directory.

mchr