Writing my first Ant task: what am I missing?

238 Views Asked by At

I have read this article and used it to write my first Ant task called AutoTestTask:

public class AutoTestTask extends org.apache.tools.ant.Task {
    // ...
}

I have also compiled and packaged this object into auto-test.jar.

If my understanding of Ant is correct, then to include it as part of another project's build, I use the following XML:

<project name="SomeProject" basedir="." default="deploy" xmlns:at="antlib:org.me.auto-test">
    <!-- Task definitions. -->
    <taskdef name="at-autotest" classname="org.me.auto-test.AutoTestTask"/>

    <!-- Use the task. -->
    <at:autotest/>
</project>

I believe I also need to copy auto-test.jar into my ${ANT_HOME}/lib directory - can someone please confirm? What's confusing me is the xmlns:at="antlib:org.me.auto-test" attribute at the top of the XML, and specifically, the antlib:<whatever> portion. Is this some kind of Ant-specific protocol that says "*anything qualified by the at namespace will be found inside ${ANT_HOME}/lib with a root package of org.me.auto-test*"? If not could someone explain what it means?

Also, if I'm missing anything obvious or have anything configured incorrectly, please let me know. Thanks in advance!

4

There are 4 best solutions below

0
On BEST ANSWER

OK, it's simpler than you think, but you have to be a bit careful.

The first problem is <taskdef name="at-autotest" .. />, because then you try to use the task as "at:autotest". "at" is the xml namespace prefix, so you need to drop the "at-" at the beginning of your taskdesk definition.

The second problem is that you haven't associated your taskdef with the xml namespace "antlib:org.me.auto-test", so you can't use the prefix. At this stage, you could use it with the current namespace (i.e. no prefix) as in <autotest/>. But I encourage you to specify a separate namespace for all your external tasks, so the correct version is:

<project name="SomeProject" basedir="." default="deploy" xmlns:at="antlib:org.me.auto-test">
    <!-- Task definitions. -->
    <taskdef name="autotest" classname="org.me.auto-test.AutoTestTask" uri="antlib:org.me.auto-test"/>

    <!-- Use the task. You can use the prefix "at:" here -->
    <at:autotest/>
</project>

A couple more things:

  1. this setup forces you to place your jar for the task class into ${ANT_HOME}/lib. But you don't have to do this, you can refer to the jar directly if you know the location (for example, a lib folder in your project root folder). You can specify a classpath containing the jar with <taskdef>, as in (assuming you have defined that classpath and assigned id="autotest.classpath"):

    <!-- Task definitions. -->
    <taskdef name="autotest" classname="org.me.auto-test.AutoTestTask" 
           uri="antlib:org.me.auto-test" classpathref="autotest.classpath" />
    
  2. As suggested by another person here, you can package your class in an antlib altogether. The only difference with the jar is that it includes a file 'antlib.xml" and that you can even skip the taskdef declaration if this jar is in the main classpath already. Read up here. This is where the "antlib:" namespace prefix brings some bonus. I personally don't like putting things in ${ANT_HOME}/lib so I'm happy to use the <taskdef /> with the classpath, but I would still recommend to package your jar as an antlib, and to use antlib: as a namespace prefix as a convention anyway.

0
On

You're trying to package your task as an antlib. The XML file will match the namespace and contain the taskdef operation.

antlibs are relatively new, which might explain why some older "how to create an ANT task" tutorials make no mention of them.

0
On
  1. I can't compile a package with a hyphen, so I suggest you change auto-test to autotest
  2. In taskdef you have at-autotest, should be autotest
  3. xmlns declaration is for xml parser and for using antlibs. You don't need to use them for your first ant task. So: remove xmlns and at: prefix.

Since you ask "What am I missing", please report what is the error message you get. Possibly after following the above suggestions.

0
On

Mostly creating a new ant task via extending org.apache.tools.ant.Task is overkill.
Notice there are other ways too :
Use scriptdef combined with a scripting language that has full access to ant api i.e.Groovy, Javascript
(jdk >= 6 ships with with its own builtin javascript engine based on rhino 1.6) to define a task inside ant.
To bundle your stuff afterwards create some commons.xml that contains all your scriptdef and macrodef and use import to make it available for other ant scripts.