Table of Contents

How′s It Useful?

   JWare/AntXtras Foundation (AntXtras) enhances Ant with a variety of new types, conditions, tasks, and behaviors that make it easier for you to use Ant to solve many kinds of problems. Below we list some of the key reasons to use AntXtras along with links to additional feature information.

Variables

Why add mutable properties aka variables to Ant? Because variables let you eliminate a lot of property clutter from your Ant runtime environment particularly when a single target, macrodef, or condition with fixture setting side-effects is executed multiple undefined times. Take for instance, a variable that lets you calculate how long any set of tasks took to execute, or a variable that tracks the list of failing tests from a large set of externally run test suites, or a variable that lets you define the initial value of your deployment status as “GREEN” but allows subsequently run tasks to downgrade the status to “AMBER” or “RED”. In all three cases, there is a single variable that many different tasks in different contexts (target, project, macrodef) can read, update, and even delete.

:!: One feature of AntXtras variables is that they are distinct from standard Ant properties but you use them in almost an identical manner. Other Ant extensions have altered the standard readonly behavior of standard properties so it is possible that a setting you think is predefined and static is not. AntXtras leaves standard properties alone; we believe their immutable quality is quite important in predicting the outcome of executing an Ant script with certain parameters. We have chosen instead to supplement this write-once-read-many set of fixture controls, with another totally different kind (variables) that in addition to mutability, also support a scope different from standard properties. Unlike standard properties which are bound by a project, by default variables live at the thread scope which means you can declare and manipulate variables between projects and other isolated execution contexts. So a main build can declare and read variables passed to its sub-builds, for instance, without any additional support for each individual task implementation.

Function Shortcuts

Why add function shortcuts aka funcuts to Ant? Because, a great many of Ant′s components do single, simple things that we can represent in a form far less verbose than the standard, explicit Ant XML notation. We virtually never use these simple components in isolation; instead, we use them to provide scaffolding or some other support function for a more complex activity. In keeping with the AntXtras goal to do more with less, we created function shortcuts to eliminate the need for wordy script and transient properties; instead we expose fixture, utility tasks and Ant functions using the standard Ant property dereference semantics and a simple property naming convention that identifies the thing you want done.

The general form of a function shortcut is ${$scheme:[fragment]} where the $scheme: portion selects one of a script-controlled set of function shortcuts and the optional fragment portion defines a query specific to a request (and scheme). The AntXtras function shortcut mechanism is open-ended; just as you can define additions to Ant’s standard conditions, tasks, and other types, you can rename most of our funcuts or add your own to AntXtras. Read the Function Shortcuts Guide to get a full description of function shortcuts and an overview of the extensive funcuts antlib AntXtras includes as part of its core feature set. Some examples of typical function shortcut calls are shown below:

Recursive Property Expansion

Why add recursive property expansion to Ant? Because sometimes you have properties whose final names are determined by yet other properties. This is often the case for configuration structures whose locations are described as one of a set of possible choices (their final names), but who’s name selection is determined by another dynamic unknown context that you can represent as a second property (say the operating-system name or a host’s name or the environment against which the script is targeted). Recursive property expansion lets you finally use constructs like “${setup.${platform}.properties}” that naturally express simple property dependencies.

Recursive property expansion also works naturally with the AntXtras function shortcuts feature. Because function shortcuts rely on the standard property expansion mechanism (it’s triggered by a special property expansion handler AntXtras installs), there had to be a way to pass properties, variables, references, and other function shortcut results into a function shortcut easily. Recursive property expansion fulfills this requirement nicely as it lets you use constructs like “${$basename:${filename}|$lowercase:}” that naturally expresses the call to the function shortcut and its parameters using standard left-to-right property dereference semantics.

Enhanced Flow Control

Why tinker with Ant′s “act only on sets of resources” view of the world? Because even in its basic components, Ant itself admits that sometimes you need to execute actions based on criteria that have nothing to do with the resources that might be involved (the common “if” and “unless” attributes being one example of this realization). AntXtras just makes it simple to express such criteria for a new range of situations in variety of self-documenting ways, without making your Ant script look like a Java or JavaScript or Groovy program.

You can separate the AntXtras flow control components into two general groups: the do-er tasksets, and the protect-er tasksets. The do-er taskset will execute its enclosed tasks zero or more times provided some criteria is met. Tasks like <do>, <dowhile>, <domatch>, <doforeach> are all do-er tasksets. Read our article “Do-ers” for an in-depth look at these flow control components. The protect-er taskset will execute its enclosed tasks unconditionally but lets you define an another set of tasks to execute in the event that something goes wrong and the primary taskset is terminated prematurely. Tasks like <protect> and <isolate> are protect-er tasksets. Whether or not you define the recovery tasks explicitly depends on the protect-er taskset.

Why add exception handling to Ant? Because not all runtime issues your script encounters are catastrophes; in fact, many issues are manifestations of “known unknowns” that the script’s author can workaround or ignore. In AntXtras, we also acknowledge that a running Ant script is executing Java code ultimately, which means it can follow Java execution patterns (good or bad– take exceptions for instance). Our protect-er flow control components give you the power to create simple yet strong Ant scripts that handle these predictable JRE behaviors, like exceptions, elegantly. AntXtras provides a streamlined way for you to detect, classify, handle, or propagate such issues. If the problem really should stop the running script, AntXtras lets you clean up, rollback, and propagate additional context for subsequent review.

Overlays, Bubbles, and Nets

Why add overlays, bubbles, and nets to Ant? Because sometimes you really want to limit the fixture changing side-effects of a piece of Ant script to the request or thread context or, alternatively to a subset of tasks that exist within a larger target or macrodef. By default, Ant provides you with a single global collection of write-once, read-many properties as the primary tool to configure the execution fixture. And generally, global properties work fine. However, sometimes you want to affect the fixture for a specific set of tasks only without affecting subsequently executed tasks (including a re-execution of the same tasks but in a different call possibly with different parameter values). AntXtras calls this sort of control scoped configuration. Typically, you apply scoped configuration at the execution cycle level where it can affect all enclosed executed tasks, regardless of their declared project or target. The AntXtras <overlay> and <overlaymessages> are two examples of scoped configuration tasksets.

AntXtras has two special kinds of scoped configuration tasksets: bubbles and nets. You use bubbles to isolate the effect of the enclosed tasks on the project environment without creating a separate sub-project that must re-parse all project files. The <isolate> taskset is an example of a bubble. On the other hand, you would use nets to filter existing fixture information, or overlay different values for existing properties for the enclosed tasks. Unlike a bubble, a net will allow certain modifications to seep through to the current project′s environment even while it blocks other information from being seen or modified.

Requirements, Fallbacks, and Checks

Capture Ant output without Loggers

Why add another way to capture Ant output? Because Ant′s single “all or nothing″ approach to capturing its console output is either inadequate or overkill for doing many common information capture activities. First, Ant′s logging must be setup on the command-line that launches the Ant process using special startup properties. If these properties are not setup, there is absolutely nothing you can do from within the Ant script itself to capture information. Second, just what Ant logs and when it logs it has been predetermined by the Ant developers; out-of-the-box Ant does a good job of propagating important events but there′s no way for you to pull along additional information that the Ant developers have not included and there′s no way for you to limit the scope of the logging— all tasks, all targets, all sub-builds, all messages, everything gets logged. Third, the built-in logger that is most useful for filtering out unwanted cruft requires the Log4J system, which is valueless unless you′re already using that logging system.

The Log4Ant project tries to create a robust holistic alternative to the built-in Ant logging mechanism; however, AntXtras does give you a way to capture not only Ant log messages, but also standard (Java) System I/O for any group of tasks. You do not need to setup external listeners or properties; your script can determine whether to capture information or not. And because the information is captured within the Ant runtime, you can save the captured information to other fixture elements like properties or variables for additional processing– within Ant itself, leveraging all the Ant goodies at your disposal– before saving (or sending) to a final external sink like a file.

External Messages Files

Why not embed messages directly in the Ant script? Because keeping human-readable messages separate from the actual nuts-n-bolts Ant script is a good practice. In general separate files will let you: remove all the visual clutter of verbose messages from the body of the script implementation, keep the global Ant properties map free from non-fixture related information (a real boon when this map is exported as part of a report), tweak the messages independent of actual Ant script and of the original author, and last but certainly not least, take advantage of additional features like message templates for argument substitution and localization for different audiences.

The AntXtras external messages feature is based on the standard JRE support for locale-aware message templates and resource bundles; in particular, Properties based resource bundles. Virtually all AntXtras components that can provide feedback in messages know how to read external messages. However, to ensure you can use these messages anywhere you need a string (for example as the message passed to the regular <echo> task), AntXtras provides both a function shortcut for extracting messages and a <copymessage> task for copying a message into a fixture element like a regular property or an AntXtras variable.

The “Thread” as a First Class Context

Why expose the Ant execution thread as part of the fixture? Because implementation details like how you might organize your Ant script files (builds vs. sub-builds or internal vs. public targets or one thread vs. many threads), should not unduly impact the ability of all of these bits of script to have access to a shared changeable fixture that spans the standard task, target, and project boundaries. For many jobs, this shared fixture must include items and contexts other than simple property values; for example, many of the configuration tasksets in AntXtras, install their context at the thread level, so that calls to sub-builds or spawned child threads, automatically pick up the context as installed by the parent.