Ant: Global Concepts
- Developing in a Standard Directory Tree
- Creating Standard Ant Targets and What They Should Do
- Exploring Ant Data Types
- Listeners and Loggers
- Predefined Properties
- The Ant Command Line
- Summary
We'll begin this chapter with a description of a standard development directory structure. We'll show you what is generally used for different types of projects and explain why you should consider adopting it for your own projects.
NOTE
What we'll be showing you is a common structure, but there are other layouts that you may choose to use. Ant makes it easy to work with just about any layout you can dream up.
We'll then move on to more "standard" stuff. In this case, it's a discussion of what to call your targets. There are certain targets that just about every build file you run across will contain, and there are others that just make good sense. We'll discuss all of these.
Next, we'll discuss what are known as Ant data types including tags to generate sets of files matching certain criteria, path-like structures, and filters.
Moving on, we'll cover loggers and listeners. These facilities provide the capability to control how your builds are logged (loggers) and to trigger behavior when certain lifecycle events occur (listeners).
Finally, we will discuss those properties that are defined automatically by Ant, how they are useful, and the command line arguments that Ant accepts.
NOTE
Unlike most of the other chapters in this book, there are no Java source files that can be downloaded from the publisher's Web site, nor is there a working build file. The reason for this is the sheer volume of topics that will be covered and the near impossibility of devising a project incorporating all of them. You can, however, download a build file that contains each of the Ant snippets that will be presented so that you can paste them in to your own build files. This file won't be able to run by itself. Just think of it as a snippet repository.
Developing in a Standard Directory Tree
With a title like that for this section, you're probably thinking this sounds about as exciting as reading a dictionary, but hold on! This is stuff you need to know. In this section, we'll to cover a standard directory tree structure for your projects. Obviously, there isn't actually a standard for this type of thing yet, but this is a good starting point.
Directory Tree for Simple Projects
Let's begin by talking about the base structure for any type of project and then move into Web applications. For most applications, you'll have source code (otherwise, why would you need Ant?) that must be compiled, and you'll also have .class files that must go somewhere. You'll (probably) create some sort of archive file and it must live somewhere. If you're running unit tests on your code (you are, aren't you?), you'll want to store the output and subsequent reports someplace as well. If you use a custom MANIFEST.MF file, you'll want to store it somewhere, too. All these files and directories should live under a project directory. For example, if you have a project called "My Project," you would store everything related to this project in a directory called myproject. Where the project directory lives is up to you. I generally have all of my project directories under a src directory. We'll lay out a simple project called myproject. Listing 3.1 shows how you might lay this out.
Listing 3.1 A Sample Directory Structure
D:\SRC\ (or /home/jgibson/src on a UNIX box) myproject\ src\ build\ reports\ etc\ doc\ lib\
That's a good start. You can see that the src directory is under the myproject directory. The src directory will house all your source files, which, as you'll soon see, must be in their own directory structure, matching the package structure of the classes. Next is the build directory. You'll recall from Chapter 2 that we dumped our compiled Java classes under this directory in a subdirectory called classes, and that's where we built our JAR file. The reports directory is new. It's where you can have your unit tests write their output and generate testing reports. The next directory is etc, which is where your MANIFEST.MF file should live until you are ready to include it in a JAR file. The doc directory is where you should place any documentation for the project, such as use case documents and UML models. If you generate JavaDoc from your sources, you should have it generated in a subdirectory of doc called javadoc or api. (I've seen more instances of api than javadoc, and I actually prefer api.) Finally is the lib directory, which is where you should place third-party JAR files that your project depends on. You could leave these third-party JARs in their own install directories, but then you would have to worry about installing a new version and how that would affect this project. If you copy the JARs for the versions you are using to your lib directory, that concern goes away.
NOTE
An excellent paper by Steve Loughran, titled "Ant In Anger: Using Apache Ant in a Production Development System," is available in the doc directory of the Ant distribution (ANT_HOME/docs/ant_in_anger.html). In this paper, Mr. Loughran recommends having a bin and a dist directory. He recommends placing "common binaries [and] scripts" in this directory. You could also use the bin directory to store startup scripts or batch files that you'll used to start your finished program or if you have a C program that is the launcher for your Java program. The dist directory is where you would package everything for distribution. In other words, this is where you'd create a Zip file that would include all your source and support files so that others could download the kit and build your project for themselves.
When you get to Chapter 4, you'll read about the javac task that executes the Java compiler on your source files. One of the things that this task is capable of doing is an incremental compile. An incremental compile is one in which only those files that have changed since the last build will be compiled. This is a great feature, but there is a requirement for getting it to work. The requirement is that the source files must live in a directory structure that mimics the package structure defined in the classes, and that will ultimately be built on compilation. In other words, if your classes live in the chapter3.actions package, you must have a directory called actions under a directory called chapter3 in your src directory. Listing 3.2 shows this.
Listing 3.2 The Requirement for Incremental Compilation
D:\SRC\ (or /home/jgibson/src on a UNIX box) myproject\ src\ chapter3\ actions\ dao\ utils\ build\ classes\ reports\ etc\
If you have other packages, either under chapter3 or siblings of it, you must create those directories as well. This might seem like a hassle, but it really isn't that big of a deal. After you get used to it, you won't even think about. In addition, most of the current integrated development environments (IDEs) will create the source files in the package structure for you automatically, so you don't even have to think about it.
Now that the directory structure is laid out, let's populate it with a few files just to drive home what goes where. I've already mentioned the source files, the MANIFEST.MF, the unit testing reports, and the classes. Let's see where those files might fall in Listing 3.3.
Listing 3.3 Files in the Directory Structure
D:\SRC\ (or /home/jgibson/src on a UNIX box) myproject\ src\ chapter3\ actions\ MyAction.java MySecondAction.java dao\ CompanyDAO.java EmployeeDAO.java utils\ CacheManager.java build\ classes\ reports\ TEST-chapter2.test.TestAll.xml TESTS-TestSuites.xml etc\ MANIFEST.MF
After you execute a compile, you'll end up with a directory structure inside the build directory that matches the directory structure under myproject/src. Listing 3.4 illustrates this for our example. (I've omitted everything but the build structure for brevity.)
Listing 3.4 The Binary Package Structure
myproject\ build\ classes\ chapter3\ actions\ MyAction.class MySecondAction.class dao\ CompanyDAO.class EmployeeDAO.class utils\ CacheManager.class
Basic Structure for a Web Application
If you're building a Web application, you'll still need this basic structure, but you'll need to add a bit to it. For a Web app, you typically have some JavaServer Pages (JSPs) and/or Java servlets. You're required to have a file called web.xml and, depending on your Web container, you might have a vendor-specific file or two as well. Just like the MANIFEST.MF file, you can put your web.xml file and the vendor-specific file (if you have one) into the etc directory. You'll also need to create a Web archive, or WAR, file. If you have any images or tag library descriptors, you'll need to house them, too. Listing 3.5 presents the Web app structure. There's not much difference, just a few extra files.
Listing 3.5 The Structure for a Web Application
D:\SRC\ (or /home/jgibson/src on a UNIX box) myproject\ src\ chapter3\ actions\ MyAction.java MySecondAction.java dao\ CompanyDAO.java EmployeeDAO.java servlets\ MyServlet.java utils\ CacheManager.java jsp\ index.jsp build\ mytest.war classes\ reports\ TEST-chapter3.test.TestAll.xml TESTS-TestSuites.xml etc\ MANIFEST.MF web.xml tld\ mytags.tld images\ banner.png
Using a directory structure like this will greatly help you in your development. One practice I've seen that I'd like to discourage is that of editing your source files in the same directories as your .class files. The problem this creates is that you have source and binaries in the same place. Why is this a problem? Because a typical clean target is defined as a delete task that just blasts the build directory. If your source as well as your binaries are in the build directory, you surely don't want to delete it. You would have to give filtering parameters to the delete task to avoid deleting your source. It's really much easier to keep your source an