I’m so used to the way Netbeans treats the process of building and deploying my Java projects that I completely neglected one of the most powerful tools I had ever met: Apache Ant.
Actually, Netbeans wasn’t the only reason of my neglect. My own laziness have a big part on it. In the few times I had to read an Ant build script (always generated by Netbeans) I felt a certain angst of all that XML code. It always made me remember when I used to work with GNU make. Besides that, I’m not a big XML based DSL fan. Until I had to automate the process of deploying one of my applications using Java Webstart.
This application uses Spring + Hibernate. As a consequence, I have lots of jar files to deploy. The process consist in:
- Sign all my jar files
- Generate a JNLP file
- Deploy all the files above to the server
Actually, Netbeans is progressing in this task , but it still isn’t right where I need. So, until then I had to manually (SHAME ON ME!!!) execute this task. My first attempt was to write a Groovy script. But just by accident I discovered a set of ant tasks named Orange Volt which led me to finally learn Apache Ant. And the result was just WONDERFUL!
After all this rant about Ant, I must at least describe this beast. It’s a build tool similar to GNU Make. Actually, I see it as a make refined at it’s best. All the annoyances of make are gone in ant: no more problems with characters like tab, and what is even more interesting: instead of being based on commands of the local machine, Ant is based on Java classes. As a consequence, Ant scripts are easier to transport among different computers. And the XML syntax for my surprise is actually quite useful in this case!
Installing Ant
Installing Ant is quite easy:
- Download the latest version at: http://ant.apache.org
- Unpack the downloaded file in any directory you want.
- Declare a system variable named ANT_HOME. This variable value must be the directory which you unpacked your Ant distribution.
- Add the ANT_HOME/bin directory to your system path
- Check if the JAVA_HOME variable is already declared on your system.
To test your installation, just type ant on your system shell. If everything is ok, the following prompt will appear:
Buildfile: build.xml does not exist! Build failed
Using Ant
An Ant build script consist in an XML document similar to the following example:
<project name="myProject" default="dist" basedir="."> <description> An useless Ant script! </description> ... <target name="dist"> <!-- Maybe I'll do something --> </target> </project>
This file must be named build.xml. When you execute the ant command, Ant will seek for this file on your current directory (it’s the default behavior). As you can see on the above example: the root element of this document is called project.
The main attributes of this tag are:
name: the name of the project
default: the default target to be executed
basedir: the base directory of the script.
The description is optional. It’s used for documentation uses only.
An Ant project may have more than one target. A target is a set of tasks to be executed by the script. As in make, you may also define dependencies among targets as in the following example:
<project name="project" default="deploy" basedir="."> <target name="copy"> ... </target> <target name="compile"> ... </target> <target name="deploy" depends="compile, copy"> ... </target> </project>
In the above example, the deploy target is the default target executed by the script. But before it is executed, the compile and copy targets must be executed (they are the dependencies).
If you want, you can also execute a specific target by the command line. In this case, you only have to type the command ant [name of the target]
Tasks
As a project is composed of targets, a target is composed of tasks. You may see a task as a command to be executed. To add a task to a target, you will (as everything in Ant) use plain pure XML syntax like bellow:
<task_name attribute1="value1" attribute2="value2" ... attributeN="valueN"/>
Ant already comes with several core tasks ready to use, which list can be seen on this link.
To better understand how to use tasks, here is a quick example:
<project name="backup" default="backup" basedir="."> <property name="destiny" location="../backup"/> <target name="backup"> <mkdir dir="${destiny}"/> <zip destFile="${destiny}/backup.zip" basedir="."/> </target> </project>
This script will execute the backup target. It’s first action will be to execute the task mkdir. As it’s name already says, it will create a new directory (just in case it doesn’t exist) using the value defined on the property destiny.
A property is actually a global variable used by the Ant script. In this case, the destiny property is referring to a directory (that’s why I used the location attribute).
This property was used on the mkdir task using a syntax really close to the EL:
<task attribute_name="${property_name}"/>
After the execution of the mkdir task, the zip task is called. As it’s name already says, it will generate a zip file based on the two attributes I declared.
TIP: Ant have a GREAT online manual: http://ant.apache.org/manual/index.html
Writing your own tasks
Of course the Ant core tasks aren’t going to answer ALL your needs. In these cases, it’s possible to write your own. On the Ant manual there’s a great guide of how to do it: http://ant.apache.org/manual/developlist.html
With your own tasks ready, these must be packed on a jar file which then must be copied to the ANT_HOME/lib directory. (you may also add your jar files to your classpath if you want)
Here is an example of how to use external tag libraries in your own scripts:
<project name="blabla" basedir="." default="blablaTask"> <taskdef name="mytask" classname="packate.where.your.task.is.Task" /> ... </project>
To use an external task, you must declare the taskdef task in the project tag. It have two main attributes:
name: the name of your task (how you’ll declare it on your build script
classname: the complete class name
So, to see how your custom task could be used, let me complete the above example:
<project name="blabla" basedir="." default="blablaTarget"> <taskdef name="mytask" classname="caminho.para.sua.Task" /> <target name="blablaTarget"> <mytask attribute1="some value" attribute2="another value"/> </target> </project>
Remember: you may only declare tasks inside targets!
Usefull core tasks
In my short experience with Ant. Some of it’s core tasks where really usefull for me:
signjar: used to sign your jar files
jar: generate jar files
war/ear: it’s actually a specialization of the jar task. Used to generate .war and .ear files.
tar: used to create tar files.
zip/unzip: Compress/decompress files using the ZIP format.
patch: applies a diff file to originals
sync: synchronized a target directory with the files stored on another location.
Conclusions
- Laziness generate ignorance :). It’s always a good thing to see things outside your favorite IDE.
- Ant XML syntax is pretty handy. But if you don’t like it, you may also try GANT (it’s WONDERFUL for me how Groovy can always make things more elegant!)
- Ant is easy!
- Try not to get too much addicted to Ant (as I’m right now)
Try Maven 2! Instead of Ant..
You are right. I tryed maven2 and run screaming away. It was like EJB2^2.
Wow… good luck in the real world, guys.
I agree with the conclusion – take a look at gant. ant dsl for groovy.
Ant was great… some eras ago ;) Now it is rather treated as a very bad tool and should rather be avoided. Even the author of Ant has admitted it. You should rather try building your projects with Apache Maven. Netbeans IDE has also integration for it.
I agree that Maven 2 is even better, but it has a bit of a learning curve. It also supports Ant tasks, but it gives you a whole lot more.