Ant in Action
Second Edition of Java Development with Ant
Steve Loughran and Erik Hatcher
  • July 2007
  • ISBN 9781932394801
  • 600 pages
  • printed in black & white owe it to yourself to read this book.

Kevin Jackson, Ant Committer

Ant in Action is a complete guide to using Ant to build, test, redistribute and deploy Java applications. A retitled second edition of the bestselling and award-winning Java Development with Ant, this book contains over 50% new content including:

  • New Ant 1.7 features
  • Scalable builds for big projects
  • Continuous integration techniques
  • Deployment
  • Library management
  • Extending Ant

Whether you are dealing with a small library or a complex server-side system, this book will help you master your build process. By presenting a running example that grows in complexity, the book covers nearly the entire gamut of modern Java application development, including test-driven development and even how to set up your database as part of the deployment.

Table of Contents show full

preface to the second edition

foreword to the first edition

preface to the first edition


about this book

about the authors

about the cover illustration

Introduction to the Second Edition

Part 1 Learning Ant

1. Introducing Ant

1.1. What is Ant?

1.1.1. The core concepts of Ant

1.1.2. Ant in action: an example project

1.2. What makes Ant so special?

1.3. When to use Ant

1.4. When not to use Ant

1.5. Alternatives to Ant

1.5.1. IDEs

1.5.2. Make

1.5.3. Maven

1.6. The ongoing evolution of Ant

1.7. Summary

2. A first Ant build

2.1. Defining our first project

2.2. Step zero: creating the project directory

2.3. Step one: verifying the tools are in place

2.4. Step two: writing your first Ant build file

2.4.1. Examining the build file

2.5. Step three: running your first build

2.5.1. If the build fails

2.5.2. Looking at the build in more detail

2.6. Step four: imposing structure

2.6.1. Laying out the source directories

2.6.2. Laying out the build directories

2.6.3. Laying out the distribution directories

2.6.4. Creating the build file

2.6.5. Target dependencies

2.6.6. Running the new build file

2.6.7. Incremental builds

2.6.8. Running multiple targets on the command line

2.7. Step five: running our program

2.7.1. Why execute from inside Ant?

2.7.2. Adding an "execute" target

2.7.3. Running the new target

2.8. Ant command-line options

2.8.1. Specifying which build file to run

2.8.2. Controlling the amount of information provided

2.8.3. Coping with failure

2.8.4. Getting information about a project

2.9. Examining the final build file

2.10. Running the build under an IDE

2.11. Summary

3. Understanding Ant datatypes and properties

3.1. Preliminaries

3.1.1. What is an Ant datatype?

3.1.2. Property overview

3.2. Introducing datatypes and properties with <javac>

3.3. Paths

3.3.1. How to use a path

3.4. Filesets

3.4.1. Patternsets

3.5. Selectors

3.6. Additional Ant datatypes

3.7. Properties

3.7.1. Setting properties with the <property> task

3.7.2. Checking for the availability of files: <available>

3.7.3. Testing conditions with <condition>

3.7.4. Creating a build timestamp with <tstamp>

3.7.5. Setting properties from the command line

3.8. Controlling Ant with properties

3.8.1. Conditional target execution

3.8.2. Conditional build failure

3.8.3. Conditional patternset inclusion/exclusion

3.9. References

3.9.1. Viewing datatypes

3.10. Managing library dependencies

3.11. Resources: Ant’s secret data model

3.12. Best practices

3.13. Summary

4. Testing with JUnit

4.1. What is testing, and why do it?

4.2. Introducing our application

4.2.1. The application: a diary

4.3. How to test a program

4.4. Introducing JUnit

4.4.1. Writing a test case

4.4.2. Running a test case

4.4.3. Asserting desired results

4.4.4. Adding JUnit to Ant

4.4.5. Writing the code

4.5. The JUnit task: <junit>

4.5.1. Fitting JUnit into the build process

4.5.2. Halting the build when tests fail

4.5.3. Viewing test results

4.5.4. Running multiple tests with <batchtest>

4.6. Generating HTML test reports

4.6.1. Halting the builds after generating reports

4.7. Advanced <junit> techniques

4.8. Best practices

4.8.1. The future of JUnit

4.9. Summary

5. Packaging projects

5.1. Working with files

5.1.1. Deleting files

5.1.2. Copying files

5.1.3. Moving and renaming files

5.2. Introducing mappers

5.3. Modifying files as you go

5.4. Preparing to package

5.4.1. Adding data files to the classpath

5.4.2. Generating documentation

5.4.3. Patching line endings for target platforms

5.5. Creating JAR files

5.5.1. Testing the JAR file

5.5.2. Creating JAR manifests

5.5.3. Adding extra metadata to the JAR

5.5.4. JAR file best practices

5.5.5. Signing JAR files

5.6. Testing with JAR files

5.7. Creating Zip files

5.7.1. Creating a binary Zip distribution

5.7.2. Creating a source distribution

5.7.3. Zip file best practices

5.8. Packaging for Unix

5.8.1. Tar files

5.8.2. Generating RPM packages

5.9. Working with resources

5.9.1. A formal definition of a resource

5.9.2. What resources are there?

5.9.3. Resource collections

5.10. Summary

6. Executing programs

6.1. Running programs under Ant—an introduction

6.1.1. Introducing the <java> task

6.1.2. Setting the classpath

6.1.3. Arguments

6.1.4. Defining system properties

6.1.5. Running the program in a new JVM

6.1.6. JVM tuning

6.1.7. Handling errors

6.1.8. Executing JAR files

6.2. Running native programs

6.2.1. Running our diary as a native program

6.2.2. Executing shell commands

6.2.3. Running under different Operating Systems

6.2.4. Probing for a program

6.3. Advanced <java> and <exec>

6.3.1. Setting environment variables

6.3.2. Handling timeouts

6.3.3. Running a program in the background

6.3.4. Input and output

6.3.5. Piped I/O with an I/O redirector

6.3.6. FilterChains and FilterReaders

6.4. Bulk operations with <apply>

6.5. How it all works

6.5.1. <java>

6.5.2. <exec> and <apply>

6.6. Best practices

6.7. Summary

7. Distributing our application

7.1. Preparing for distribution

7.1.1. Securing our distribution

7.1.2. Server requirements

7.2. FTP-based distribution of a packaged application

7.2.1. Uploading to Unix

7.2.2. Uploading to a Windows FTP server

7.2.3. Uploading to SourceForge

7.2.4. FTP dependency logic

7.3. Email-based distribution of a packaged application

7.3.1. Sending HTML messages

7.4. Secure distribution with SSH and SCP

7.4.1. Uploading files with SCP

7.4.2. Downloading files with <scp>

7.4.3. Remote execution with <sshexec>

7.4.4. Troubleshooting the SSH tasks

7.5. HTTP download

7.5.1. How to probe for a server or web page

7.5.2. Fetching remote files with <get>

7.5.3. Performing the download

7.6. Distribution over multiple channels

7.6.1. Calling targets with <antcall>

7.6.2. Distributing with <antcall>

7.7. Summary

8. Putting it all together

8.1. How to write good build files

8.2. Building the diary library

8.2.1. Starting the project

8.2.2. The public entry points

8.2.3. Setting up the build

8.2.4. Compiling and testing

8.2.5. Packaging and creating a distribution

8.2.6. Distribution

8.3. Adopting Ant

8.4. Building an existing project under Ant

8.5. Summary

Part 2 Applying Ant

9. Beyond Ant’s core tasks

9.1. The many different categories of Ant tasks

9.2. Installing optional tasks

9.2.1. Troubleshooting

9.3. Optional tasks in action

9.3.1. Manipulating property files

9.3.2. Improving <javac> with dependency checking

9.4. Software configuration management under Ant

9.5. Using third-party tasks

9.5.1. Defining tasks with <taskdef>

9.5.2. Declaring tasks defined in property files

9.5.3. Defining tasks into a unique namespace

9.5.4. Defining tasks from an Antlib

9.6. The Ant-contrib tasks

9.6.1. The Ant-contrib tasks in action

9.7. Code auditing with Checkstyle

9.8. Summary

10. Working with big projects

10.1. Master builds: managing large projects

10.1.1. Introducing the <ant> task

10.1.2. Designing a scalable, flexible master build file

10.2. Controlling child project builds

10.2.1. Setting properties in child projects

10.2.2. Passing down properties and references in <ant>

10.3. Advanced delegation

10.3.1. Getting data back

10.4. Inheriting build files through <import>

10.4.1. XML entity inclusion

10.4.2. Importing build files with <import>

10.4.3. How Ant overrides targets

10.4.4. Calling overridden targets

10.4.5. The special properties of <import>

10.5. Applying <import>

10.5.1. Extending an existing build file

10.5.2. Creating a base build file for many projects

10.5.3. Mixin build files

10.5.4. Best practices with <import>

10.6. Ant’s macro facilities

10.6.1. Redefining tasks with <presetdef>

10.6.2. The hazards of <presetdef>

10.7. Writing macros with <macrodef>

10.7.1. Passing data to a macro

10.7.2. Local variables

10.7.3. Effective macro use

10.8. Summary

11. Managing dependencies

11.1. Introducing Ivy

11.1.1. The core concepts of Ivy

11.2. Installing Ivy

11.2.1. Configuring Ivy

11.3. Resolving, reporting, and retrieving

11.3.1. Creating a dependency report

11.3.2. Retrieving artifacts

11.3.3. Setting up the classpaths with Ivy

11.4. Working across projects with Ivy

11.4.1. Sharing artifacts between projects

11.4.2. Using published artifacts in other projects

11.4.3. Using Ivy to choreograph builds

11.5. Other aspects of Ivy

11.5.1. Managing file versions through Ivy variables

11.5.2. Finding artifacts on the central repository

11.5.3. Excluding unwanted dependencies

11.5.4. Private repositories

11.5.5. Moving to Ivy

11.6. Summary

12. Developing for the Web

12.1. Developing a web application

12.1.1. Writing a feed servlet

12.1.2. Libraries in web applications

12.1.3. Writing web pages

12.1.4. Creating a web.xml file

12.2. Building the WAR file

12.3. Deployment

12.3.1. Deployment by copy

12.4. Post-deployment activities

12.4.1. Probing for server availability

12.4.2. Pausing the build with <sleep>

12.5. Testing web applications with HttpUnit

12.5.1. Writing HttpUnit tests

12.5.2. Compiling the HttpUnit tests

12.5.3. Running the HttpUnit tests

12.6. Summary

13. Working with XML

13.1. Background: XML-processing libraries

13.2. Writing XML

13.3. Validating XML

13.3.1. Validating documents using DTD files

13.3.2. Validating documents with XML Schema

13.3.3. Validating RelaxNG documents

13.4. Reading XML data

13.5. Transforming XML with XSLT

13.5.1. Defining the structure of the constants file

13.5.2. Creating the constants file

13.5.3. Creating XSL style sheets

13.5.4. Initializing the build file

13.6. Summary

14. Enterprise Java

14.1. Evolving the diary application

14.2. Making an Enterprise application

14.3. Creating the beans

14.3.1. Compiling Java EE-annotated classes

14.3.2. Adding a session bean

14.4. Extending the web application

14.5. Building the Enterprise application

14.6. Deploying to the application server

14.7. Server-side testing with Apache Cactus

14.7.1. Writing a Cactus test

14.7.2. Building Cactus tests

14.7.3. The Cactus Ant tasks

14.7.4. Adding Cactus to an EAR file

14.7.5. Running Cactus tests

14.7.6. Diagnosing EJB deployment problems

14.8. Summary

15. Continuous integration

15.1. Introducing continuous integration

15.1.1. What do you need for continuous integration?

15.2. Luntbuild

15.2.1. Installing Luntbuild

15.2.2. Running Luntbuild

15.2.3. Configuring Luntbuild

15.2.4. Luntbuild in action

15.2.5. Review of Luntbuild

15.3. Moving to continuous integration

15.4. Summary

16. Deployment

16.1. How to survive deployment

16.2. Deploying with Ant

16.3. Database setup in Ant

16.3.1. Creating and configuring a database from Ant

16.3.2. Issuing database administration commands

16.4. Deploying with SmartFrog

16.4.1. SmartFrog: a new way of thinking about deployment

16.4.2. The concepts in more detail

16.4.3. The SmartFrog components

16.5. Using SmartFrog with Ant

16.5.1. Deploying with SmartFrog

16.5.2. Deploying with the <deploy> task

16.5.3. Summary of SmartFrog

16.6. Embracing deployment

16.7. Summary

Part 3 Extending Ant

17. Writing Ant tasks

17.1. What exactly is an Ant task?

17.1.1. The life of a task

17.2. Introducing Ant’s Java API

17.2.1. Ant’s utility classes

17.3. A useful task: <filesize>

17.3.1. Writing the task

17.3.2. How Ant configures tasks

17.3.3. Configuring the <filesize> task

17.4. Testing tasks with AntUnit

17.4.1. Using AntUnit

17.4.2. Testing the <filesize> task

17.4.3. Running the tests

17.5. More task attributes

17.5.1. Enumerations

17.5.2. User-defined types

17.6. Supporting nested elements

17.7. Working with resources

17.7.1. Using a resource-enabled task

17.8. Delegating to other tasks

17.8.1. Setting up classpaths in a task

17.9. Other task techniques

17.10. Making an Antlib library

17.11. Summary

18. Extending Ant further

18.1. Scripting within Ant

18.1.1. Writing new tasks with <scriptdef>

18.1.2. Scripting summary

18.2. Conditions

18.2.1. Writing a conditional task

18.3. Writing a custom resource

18.3.1. Using a custom resource

18.3.2. How Ant datatypes handle references

18.4. Selectors

18.4.1. Scripted selectors

18.5. Developing a custom mapper

18.6. Implementing a custom filter

18.7. Handling Ant’s input and output

18.7.1. Writing a custom listener

18.7.2. Writing a custom logger

18.7.3. Using loggers and listeners

18.7.4. Handling user input with an InputHandler

18.8. Embedding Ant

18.9. Summary

Appendix A: Installation

A.1. Before you begin

A.2. The steps to install Ant

A.3. Setting up Ant on Windows

A.4. Setting up Ant on Unix

A.5. Installation configuration

A.6. Troubleshooting installation

Appendix B: XML Primer

B.1. XML namespaces

Appendix C: IDE Integration

C.1. How IDEs use Ant

C.3. Sun NetBeans

C.4. IntelliJ IDEA

C.5. Building with Ant and an IDE


About the Technology

The most widely used build tool for Java projects, Ant is cross-platform, extensible, simple, and fast. It scales from small personal projects to large, multi-team enterprise projects. And, most important, it’s easy to learn.

About the authors

Steve Loughran has been an active user and developer of Ant since the year 2000, a committer on the project since 2001, and a member of the Apache Software Foundation since 2004. He regularly lectures on the problems of big-system builds, distributed testing, and deployment. He is a research scientist at Hewlett-Packard Laboratories in Bristol, UK.

Erik Hatcher is an active Ant project developer and maintains jGuru's Ant FAQ and Forum. Erik has written articles for, IBM developerWorks, and JavaPro. His other open-source efforts currently include Lucene, XDoclet, and his own blogger, BlogScene. He is also the co-author of Manning's Lucene in Action. Erik lives in Charlottesville, VA.

eBook $39.99 pdf + ePub + kindle

FREE domestic shipping on three or more pBooks

If you do Java Software, and there's only one book you read this year, it should be this one.

Leo Simons, Apache Gump Developer and Senior Engineer, Joost

Don't put your build at risk by not reading this book.

Jon Skeet, Senior Software Engineer, Audatex (UK)

Absolutely recommended for any developer.

Bas Vodde, Manager Agile & Integrative Product Development Nokia Siemens Networks

It's worth buying this book for Chapter 16 alone.

Julian Simpson, Thought Works Ltd.