Myrmidon: The Ant2.0 Proposal

by Peter Donald <donaldp@apache.org>

Myrmidon is a proposal for Ant 2.0, a java based build tool. Unlike other proposals it was specifically designed as both a tool a an API library that can be reused in other domains.

To do and what not to do

There is a number of issues that this proposal addresses and a number of issues that have been deliberately elided. The focus is currently at the lower levels - namely the task execution engine, the notion of contexts/scopes, loading of tasklets, datatypes and converters etc. While it does implement a Project engine API is still being discussed on ant-dev and this proposal just adopts Ant1.x's model until a better understanding is gained of what is required.

Neither this document nor the proposal is intended to be a vision statement. Rather it is a description of how it could be implemented based on commonly accepted needs requested on ant lists and discussed by ant-dev. The vision statement is more strongly associated with the Project API and extentions (CJAN, import project trees, preprocessing via xslt/css/whatever, templating etc). And thus is not addressed here.

The Prime Directive: Execute tasks

One of the primary concerns of ant is providing a task execution environment (TEE). The TEE provides a number of services to tasks. The TEE manages the lifecycle of the tasks. This includes providing the tasks with a logger instance, context information and access to peer components. The lifecycle also involves executing init(), run() and dispose() methods at appropriate times.

Instead of reinventing the wheel this proposal instead reuses the Avalon framework that already provides facilities for many of the concepts required. It already has interfaces/classes to model concepts of context, logger, containers etc.

One of the requirements identified was the need for dynamic interpretation and instantiation of tasks. To implement this there needs to be an abstraction layer between task object instances and the objects that are manipulated by projects and tools outside tasklet API. This abstraction has the same requirements as Configuration objects in Avalon and thus the task proxies are represented by Avalons Configuration object.

SOC, IOC and the alphabet soup

The design of Myrmidon follows many of the design patterns found in Avalon. The strongest influence cna be seen from the meta-patterns; Separation of Concerns (SOC) and Inversion of Control (IOC).

SOC essentially is a design pattern used to separate the system accroding to relevent dimensions. (SOC is often called multi-dimensional SOC). The definition of "relevent" is domain specific and in our case there is a number of dimensions. For instance you will notice that there is a separation between project, tasklet, conversion and datatype functionality. Where in Ant1.x these were only partially separated or tightly coupled there is now decoupling. This separation allows easy reuse of parts in other projects. ie It is now extremely easy to reuse the tasklet api in other tools (such as Installshield type apps or Cron-like deamons etc).

Another dimension in which myrmidon is separated is by users. For instance there is a separation between engine code and client code. The client code is the code used by those who implement the components. For instance tasklet developers only have to look at client code for tasklets and never look at implementation of engine.

Inversion of Control (IOC) aka the Holywood Principle (Don't call us - we'll call you) is another pattern applied within Myrmidon. In this pattern it is the container that provides facilities and executes lifecycle by calling methods of child components. So instead of the component calling methods to lookup or create peer components or method managing it's own lifecycle the container is responsible for these functions.

These approach should be familiar to a servlet or EJB developer as they are also based on SOC and IOC except they do it at a lower resolution. For more detailed explanation of these design approaches have a look at http://java.apache.org/framework/developer/index.html.

The result of these design choices is a more flexable and reusable components.

Enough theory - give me Nuts and Bolts

The code is separated into 5 different sections. These are the project, tastlet, converter, datatype and frontend APIs. The project API is concerned with building and representing a project. The tasklet API is concerned with executing tasks in a particular environment. The converter API is concerned with converting instances of one type into another type. The datatype API is used to register, load and instantiate instances of named datatypes. The frontend API involves instantiating and managing all the other components and making it easy to build different frontends (CLI, GUI, Servlet).

When Myrmidon is started it interacts with FrontEnd API. It aquires a ProjectBuilder instance from FrontEnd API and uses it to build a project. It then aquires a ProjectEngine instance from FrontEnd again and uses it to execute the created project. This project will first execute the implicit target (which includes all of properties outside target element). And then execute the default or specified target. Each target executes it's dependencies first and then checks it's condition to see if it should execute itself. Each target contains a list of tasks (in the form of Configuraiton objects). These are passed to the tasklet API that instantiates and executes the tasks. The tasklet API instantiates the relevent task and then applies rules to use the Configuration object to configure the task. In some cases this involves resolving properties and converting values to the correct type required by task. The convertion is done by Converter API. Properties are associations between a name and a value, the types of the value aremanaged by the DataType API and accessed via the Property task.

Now if you wanted to change a certain component of the system - lets say the ProjectBuilder component. You instead want to use a component that you wrote yourself that builds a project with the result of a xslt + xml -> xml process so that you can use static templating. The way to do this would be to set the property "ant.comp.builder" to "com.biz.ant.MyXSLTProjectBuilder" before handing the properties to the FrontEnd API. The FrontEnd API would then wire together the components appropriately and the same process as documented above would be used. Other components can be replaced in a similar manner. For a full list of properties that can be set see the default FrontEnd implementation.

Now instead of replacing a component in the system say you wanted to add an extra task. In this case you would create a task "com.biz.ant.tasks.ProcessFile" that extends "org.apache.ant.tasklet.AbstractTasklet". You would then implement run() method to do the work and and setter methods to accept parameters. The run method can throw AntException if the task fails for any reason. The setter methods are in format of Ant1.x setters with one extention. The extention allows '-' characters to appear in xml names and these will be transferred into capitalisation of next character in java names. ie file-permission attribute --> setFilePermission() method. After implementing this task you would have to define it in taskdef.xml of it's archive or else define it with a taskdef construct.

In a similar method new converters and datatypes can be added to the system. For example if you needed to add a TestSet datatype that held a list of test names then this would be possible. You could also add a converter that converted a list of comma separated strings into a TestSet.

The one thing that this proposal does not address is validation concerns. You will notice that the above is mainly aimed to reduce the complexity for task developers. Where in 1.x you had to manage convertion manually (depending on version of Ant) and also had to explcitly incorporate support for datatypes manually. The one other concern that was coded into every task was validation. ie Were the correct parameters set ? It would be desirable to be able to associate meta-information with the task that indicated the required parameters. This would reduce the workload on task developers even more and encourage better task structure. This is a future TODO.

A Rose by any other name ...

The name Myrmidon is a derivation of a mythological name for some anst that were turned into soldiers by the god Zeus. It came to mean "a subordinate who executes orders unquestioningly" which seemed suitable for a task execution/build tool. A more complete description stolen from http://bondi-blue.parlez.com/previous_words/myrmidon.txt.

The appellation Myrmidon was derived from the Greek word "myrmex", meaning ant. According to Greek mythology, the Myrmidons were transformed into humans by the god Zeus as an act of kindness to his son Aeacus. King Aeacus, captivated by a colony of ants, prayed that he should receive an increase in population equal to the number of ants before him. When he awoke the next day, the ants were his human subjects. Thereafter, they were known as the Myrmidons. See "The Iliad" for Homers' account of the Myrmidons during the Trojan War.