Tech Ads

Back to Article List

Originally published June 2004 [ Publisher Link ]

Ant 1.6: New features and tasks


Ant is a Java-based build tool developed by the Apache Foundation. Thanks to its simplicity and power, Ant has made inroads into the wider Java development community. It's tailored to operate under IDEs like NetBeans and Eclipse, as well as other development tools like JUnit and XDoclet. Ant has become common on almost every Java developer workstation. In this article we will explore the new features incorporated into its latest version.

Class loading has been revamped in the 1.6 release of Ant. The optional.jar library, which contains all the non-core Ant classes, has been broken up into more manageable granular pieces, reducing the loading of unnecessary classes upon execution. Also, previously, classes had to be loaded either inside the build file or in the CLASSPATH environment variable. Now the -lib flag has been added, allowing class loading from the command line:

ant pdfdoc -lib  
  "./lib/fop.jar:./lib/batik.jar:./lib/avalon-framework.jar"

Ant relies on XML for defining its configuration parameters. XML namespace support was added to the latest release, aiding the creation of complex XML structures. Namespaces allow the presence of two equally named tasks to coexist and operate with distinct values:


<?xml version="1.0"?>
  <!-- Defining two namespaces at project level -->
 <project xmlns:production="http://linux.com/production"
         xmlns:development="http://linux.com/development">

  <!-- Declaring two resources and assigning them to
          a distinct namespace -->

 <typedef resource="com/linux/production/database.properties" 
      uri="http://linux.com/production"/>
 <typedef resource="com/linux/development/database.properties" 
      uri="http://linux.com/development"/>

  <!-- Two tasks with same name differentiated
           by a Namespace -->

  <task xmlns="http://linux.com/production">
     ...
  </task>

  <task xmlns="http://linux.com/development">
     ...
  </task>


 </project>

Macros are another welcome addition in Ant 1.6. Macros allow developers to compose programmatically defined snippets inside a project's configuration script:


<macrodef name="mylogger">
 <attribute name="type"/>
   <sequential>
    <record name="mylog.log" action="start"/>
          <echo message="Building target '@{type}'" />
    <record name="mylog.log" action="stop"/>
   </sequential>
</macrodef>


<target name="compile">
   <mylogger type="compile"/>
</target>

<target name="webapp">
   <mylogger type="webapp"/>
</target>

Here we define two targets that make use of the macro named mylogger. The actual functionality is defined in the macrodef element. The contents for our macro are declared within the sequential element, a previously available Ant task which is used to define a series of events. In this case, we create a log entry through the record task. The generated log corresponds to the type variable, which takes its value from the macro attribute provided at invocation.

One restriction which has been lifted is the allowance of top-level declarations. Previously only a few definitions were allowed to reside outside specific targets. You are now permitted to define any property at a global level for reuse within targets.


<?xml version="1.0"?>
  <project default="init" basedir=".">

   <!-- You can now declare any top level element -->
   <loadproperties srcFile="myjava.properties"/>

   <target name="init">

   <!-- Global property access -->

   </target>

  </project>

Ant libraries are another new concept. Libraries allow you to define tasks in separate XML files. In Ant circa 1.5, tasks had to be defined inside a build script either through typedef or taskdef elements. With Ant libraries, it is possible to define these elements inside an independent file and reuse them on various build scripts. Take the following Ant library:


<?xml version="1.0"?>
<antlib>

   <taskdef name="fop" 
       classname="org.apache.fop.tools.anttasks.Fop"/>

  <taskdef name="webdoclet" 
       classname="xdoclet.modules.web.WebDocletTask"/>

</antlib>

We simply nest our <taskdef> elements inside the root <antlib> tag. Assuming we place this library in a file named mylib.xml, we would use the following syntax to access its elements inside a build script:


<?xml version="1.0"?>
<project default="init" basedir=".">

 <!-- Declaring Ant library  -->
   <typedef file="mylib.xml"/>

  <target name="init">

  <!-- Using the FOP task, imported through 
          Ant libraries -->

  <fop fofile="products.fo" 
          outfile="./products.pdf"/>

  <!-- Using the WebDoclet task, imported through 
          Ant libraries -->

    <webdoclet destdir="${build.dir}">

     <fileset dir="./src/">
       <include name="**/*.java" />
     </fileset>

    <deploymentdescriptor servletspec="2.3" 
        destdir="./web/WEB-INF">

     <welcomefile file="index.jsp"/>
     <welcomefile file="index.html"/>
     </deploymentdescriptor>
   </webdoclet>

  </target>

</project>

Through the file attribute available in typedef we gain access to those tasks defined in the library. The actual invocation inside the build script is done transparently with the same name definition provided in the library.

XML namespaces are complementary to Ant libraries, in that they allow you to import a series of libraries into the same build script, and later use all of their elements in an unequivocal manner without worrying about name clashes.

All of these features are among the major enhancements in Ant 1.6, which provide both veteran and novice users new capabilities for building better and more comprehensive build scripts.


Originally published June 2004 [ Publisher Link ]

Back to Article List