How to load an optional task into ant without -lib or global installation?

The problem you are having is due to the different class-loaders in use. The Commons Net classes must be loaded by the same class-loader that loads the FTP task. Because the FTP task is loaded by Ant on start-up, you need to add the Commons Net to Ant’s classpath so that it is loaded by the same class-loader. That’s why the documentation gives you 4 different ways to do this.

I agree that none of them are ideal (the CLASSPATH environment variable being the worst). One way around this is to supply a shell script with your project that invokes Ant and passes the apporpriate -lib argument. You then get people to use this rather than invoking Ant directly. In fact, you could deviously name it ‘ant’ so that it gets run instead of the existing ‘ant’ on the path (this only works if the current directory is on the path, ahead of other directories).

The fifth option in the documentation is great in theory. They finally fixed the class-loading problems in 1.7.0. Unfortunately, as you mention, nobody retro-fitted the FTP task to take a classpath. You could try submitting an enhancement request, but this won’t help in the short term.

There is one other option, which isn’t any better than the others. Instead of making sure that the Commons Net classes are loaded by the class-loader that loads the FTP task, you could make sure that the FTP task is loaded by the class-loader that loads the Commons Net classes. To do this you have to remove the ant-commons-lib.jar file from the ‘lib’ directory of the Ant installation. This means that the FTP task won’t get loaded on start-up. This is actually why the optional tasks are broken up into so many separate JARs – so that they can be individually removed. Put this JAR file alongside the Commons Net JAR file so that it can be loaded at the same time. Then you can do something like this (I tried this and it works):

<taskdef name="ftp"
         classname="org.apache.tools.ant.taskdefs.optional.net.FTP">
  <classpath>
    <pathelement location="${basedir}/lib/ant-commons-net.jar"/>
    <pathelement location="${basedir}/lib/commons-net-2.0.jar"/>
  </classpath>
</taskdef>
<ftp server="yourserver.com"
     userid="anonymous"
     password="blah">
  <fileset dir="somedirectory"/>
</ftp>

But this is probably a worse option than just using the -lib switch (with or without a wrapper script). The only other thing I can think of is to try to find a third-party FTP task to use instead of the default one.

Leave a Comment