Alex Staveley is a software professional passionate about software engineering and technical architecture. He blogs about architectural approaches, Java topics, web solutions and various technical bits and pieces. Alex is a DZone MVB and is not an employee of DZone and has posted 48 posts at DZone. You can read more from them at their website. View Full User Profile

Are you still fond of your ANT?

  • submit to reddit

Ok you haven't caught the Maven bug and you're still using ANT. Here's two very simple Ant tips for you...

Tip 1: echoproperties

You're trying to debug things, you'd like to know details of the Ant and the JVM you're using. You'd also like to know details of the properties you have defined. You want this all quickly. Well look no further than Ant's built in target: echoproperties.

Wrap this around your own target so you can call it from the command line and that's it. I usually wrap it around a target called debug.

So I'd have something like this:

<target name="debug">

A sample output would be:
C:\Users\Alex\workspaces\staveley\sudoku>ant debug
Buildfile: C:\Users\Alex\workspaces\staveley\sudoku\build.xml
[echoproperties] #Ant properties
[echoproperties] #Fri Jun 17 20:18:35 BST 2011
[echoproperties] ant.core.lib=C\:\\tools\\buildtools\\ant\\apache-ant-1.8.0\\lib\\ant.jar
[echoproperties] ant.file=C\:\\Users\\Alex\\workspaces\\staveley\\sudoku\\build.xml
[echoproperties] ant.file.sudoku=C\:\\Users\\Alex\\workspaces\\staveley\\sudoku\\build.xml
[echoproperties] ant.file.type=file
[echoproperties] ant.file.type.sudoku=file
[echoproperties] ant.home=C\:\\tools\\buildtools\\ant\\apache-ant-1.8.0
[echoproperties] ant.library.dir=C\:\\tools\\buildtools\\ant\\apache-ant-1.8.0\\lib
[echoproperties] ant.project.default-target=help
[echoproperties] ant.project.invoked-targets=debug
[echoproperties] ant.version=Apache Ant version 1.8.0 compiled on February 1 2010
[echoproperties] basedir=C\:\\Users\\Alex\\workspaces\\staveley\\sudoku
[echoproperties] build.classes=C\:\\Users\\Alex\\workspaces\\staveley\\sudoku\\build\\classes
[echoproperties] build.dir=C\:\\Users\\Alex\\workspaces\\staveley\\sudoku\\build
[echoproperties] docs.dir=C\:\\Users\\Alex\\workspaces\\staveley\\sudoku\\docs
[echoproperties] file.encoding=Cp1252

Tip 2: Those friggin' classpaths.

You're not a java developer unless you've spent some hours in your life banging your head of the wall because your classpath was incorrect. This isn't just a beginner's problem; it can even catch season pro's out. Especially when a class or set of classes is available from multiple jars. For example, you can easily use whatever
StAX implementation you want but if you forget to put the one you want on your classpath, your runtime will use the reference implementation from the JDK. So double check your classpath before you go around boasting of the performance improvements you're getting with Woodstox!

Right, so you want a target that will echo your classpaths so you can see them how ANT sees them. Well, in ANT you can't just echo paths. But, you can make property representations of paths and then just echo them.

So let's say you set up your properties, directories and classpaths as something like
<project name="alex" basedir="." default="help">
 <property name="build.dir" location="build"/>
 <property name="build.classes" location="${build.dir}/classes"/>
 <property name="src.dir"   location="src"/>
 <property name="tests.dir" location="test"/>
 <property name="lib.dir"   location="lib"/>
 <property name="docs.dir"   location="docs"/>
 <property name="junit.jar" location="${lib.dir}/junit-4.8.2.jar"/>
 <property name="test.class" value="com.staveley.sudoku.AllTests"/>
 <path id="compile.classpath">
  <pathelement location="${build.classes}"/>
 <path id="test.classpath">
  <path refid="compile.classpath"/>
  <pathelement location="${junit.jar}"/>
 <path id="junit.task.classpath">
  <fileset dir="${lib.dir}">
   <include name="ant-junit.jar"/>

All you do is create a target, which defines properties that represent these paths and
then you echo these properties.
<!--  Outputs classpaths to console. Useful for debugging etc. -->
<target name="echo.classpaths">
 <property name="compile.classpath.string" refid="compile.classpath"/>
 <echo message="compile.classpath= ${compile.classpath.string}"/>
 <property name="test.classpath.string" refid="test.classpath"/>
 <echo message="test.classpath= ${test.classpath.string}"/>
 <property name="junit.task.classpath.string" refid="junit.task.classpath"/>
 <echo message="junit.classpath= ${junit.task.classpath.string}"/>

Sample output:
C:\Users\Alex\workspaces\staveley\sudoku>ant echo.classpaths
     [echo] compile.classpath= C:\Users\Alex\workspaces\staveley\sudoku\build\classes
     [echo] test.classpath= C:\Users\Alex\workspaces\staveley\sudoku\build\classes;C:\Users\Alex\workspaces\staveley\sudoku\lib\junit-
     [echo] junit.classpath= C:\Users\Alex\workspaces\staveley\sudoku\lib\ant-junit.jar

Notice the way I have defined the properties locally to the target. This is because they are only relevant to the target echo.classpath. There is no need to make the global. Always try to encapsulate - even in Ant.





Published at DZone with permission of Alex Staveley, author and DZone MVB.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)