Ant Scripts without XML
December 23rd, 2007It's pretty easy to create an Ant file for a simple project. A simple Ant script typically contains ubiquitous "init", "compile", "test", "war" (or "jar), "build" targets all wired together. It's easy to change and easy to understand and the script's flow has a declarative, rule-based feel to it. The problem is, projects and their build files rarely stay simple for long. Soon we need to add "validate.xml" target, junit reports, deployment to your application server and so on. Then we begin supporting multiple environments; we discover that our local desktop configuration is different from how integration environment is configured so we add numerous property files, "ftp" tasks and multiple "copy" targets for various application files. Before we know it, the build script becomes a convoluted mess of XML tags and there is nothing declarative about it anymore; it's morphed into a full-fledged, very procedural program. Perhaps we even had to resort to using ant-contrib "if" and "for" targets to implement procedural logic in Ant. And nothing is uglier than an "if" with complex conditions expressed in XML.
A better approach would be to implement "procedural" portion of the build script in Java or any of the scripting languages that Ant supports. The problem is, configuring and invoking Ant tasks from Java or a scripting language leads to verbose code. For example:
execTask = project.createTask("exec")
execTask.setOutputproperty(outputPropertyName)
execTask.setErrorProperty(errorPropertyName)
execTask.setResultProperty(resultPropertyName)
execTask.setExecutable(execName)
arg=execTask.createArg()
arg.setLine(paramString)
Doing the same thing in XML is shorter and cleaner:
<exec executable="${execName}" outputPropert="p1"
errorProperty="p2" resultProperty="p3">
<arg line="${params}" />
</exec>
So what can we do to make task invocation syntax more concise and easier to understand? In fact, the syntax could be drastically simplified with the help of simple Ant "adapters" that can be developed for popular scripting languages since Groovy, Ruby and python all have fairly intuitive syntax for supporting lists, dictionaries and other data structures. I developed such an adapter for jython. It uses python named arguments and dictionary syntax, so executing a "copy" task looks like this:
pant=PAnt(project)
pant.exTask("copy", todir="testdir", fileset={"dir":".","includes":"*.xml"} )
"PAnt" is the name of the "ant adapter" class for Jython. The class configures and executes Ant tasks based on the provided arguments using Ant task configuration API.
"pant" module also comes with a simple helper function called "nested" so that named arguments can be consistently used for nested elements. With syntax highlighting supported by most editors/IDEs (e.g., you can try PyDev for jython/python development), it allows for better visual distinctions between attribute names and values:
pant.exTask("copy", todir="testdir", fileset=nested(dir=".", includes="*.xml") )
To use "PAnt" from Ant, you can develop custom tasks using "scriptdef" or simply embed python code directly into a target:
<target name="test.pant" >
<script language="jython">
from pant import *
pant=PAnt(project)
pant.execTask(name="echo", message="foo")
</script>
</target>
The "pant" module itself is just a few lines of code as you can see from its code. Don't forget to properly setup your "python.path" if you want to make it globally available to all your Ant scripts.
There is also an open-source project Gant that provides similar (in fact, much more extensive) capabilities for Groovy, but I have not had a chance to play with it; I specifically wanted to use python/jython because jython can also be used for WebSphere Application Server administration.
In my mind scripting language-based approach for writing build files provides for much more flexible and easier to understand and maintain scripts. When you start implementing your Ant logic in python, you'll see that Ant targets become much more coarse-grained, since there is no need to create internal targets (the ones that are never invoked by the users) to simulate subroutines or conditional targets to simulate "if" statements . It is also nice to be able to use all the capabilities of a full-blown programming language as oppose a limited subset of procedural tasks that Ant provides (such as "condition"). Being able to user properly scoped variables instead of inherently global Ant properties is another great benefit.
At the same time, it is still possible to use Ant targets for expressing a flow wiring together major functions of the build script. I would prefer something less XML-like for this purpose too, but that's a task for another day.
starluck casino screenshots online casino coupons casino rama package used casino equipment northern minnesota casino manadalay bay casino casino party decoration casinos in tunica casino mississippi philadelphia harrahs joliet casino casinoalgarve casino event rama casino elko nevada blackhawk casino hotel casino craps games casino affiliate network mandalay casino casino slot internet tucson az casino riverboat casino cruises casino gambling indiana argosy casino name internet casino casino royale casino casino empress indiana winner casino wyn casino casino media group arizona casino night casino greektown job trpicana casino casino jobs london casino slots free beating the casino casino niagra falls casino rakes casino careers quinalt casino resort casino windsor poker casino israel casino hammond trump morongo casino restaurants casino gaming palace sun cruz casinos casino chance lucky casino kinder la aero player casino casino gambling sites niagara falls casinos jackpot nv casino cedars casino casino double eagle bycicle casino atlantic casino miami best casino odds casino blackjack strategy casino head indian blue chips casino lucky charm casino quinalt casino casino cda akwesasne casino casino pay check casino hodgepodge tahoe casinos brimley mi casino supercasino1000 remove casino online real casino gambling market morongo casino hotel casino kokomo indiana balleys hotel casino hardrockcafe casino california casino list loleta casino winstar casino concert casino players magazine sudbury downs casino casino palm beach michigan detroit casinos casino games craps casino+niagara commerce casino california ameristar casino council casino offline casinorama hotel casino echeck igm casino cherokee nc casino theme invitations casino game cashman cancun casinos casino established online borgatta hotel casino hollywood casino la bet365 casino uk mississippi casinos biloxi top ten casinos casino cruise miami
Found your blog while I was doing some research on a conference I just got back from. While I was here, I’ve read through some of your recent posts.
Have you taken a look at the new series of SOA events offered by ZapThink this year? I just got back from an event and really got a lot out of it. I thought it was worth passing on the link, if nothing else, just so you can take a look at what’s coming up.
In the hopes that your blog allows posts to contain Web addresses, here’s the link: www.zapthink.com/eventreg.html. And pass it on to any colleagues you think may be interested. Given that it’s still a relatively unknown event, I’m spreading the news now about it because I am hoping they can get more people there!
ZapThink’s offered me and any of my friends a $50 discount if you register with the code GAFPSOA1.
Hope you can make it, because it was definitely worth my time!
Posted by techgirl_it January 17th, 2008 at 9:36 pm[Biased opinion warning] I use the AntXtras (antxtras.sf.net) project to get flow control and other goodies in Ant scripts without the ugliness of ant-contrib. This library combined with macrodefs, presetdefs, and antlibs (three vastly under utilized features of Ant) dispense with most of the ugliness, awkwardness, and general maintenance nightmares found in many (most?) Ant scripts I’ve encountered. A lack of understanding of anything beyond buildscript-101 seems to be the underlying cause of most issues (I see the same problem reflected in Maven POM files from hell…)
-The Wabbit
Posted by The Wabbit April 8th, 2008 at 7:11 amThanks for the AntXtras pointer, I was not aware about this library. From briefly looking at the examples on the site, it looks like there is still some procedural logic (for, ifs) implemented in Ant using custom tasks. That’s what I’m trying to avoid with PAnt. BTW, you can invoke any custom task (including the ones created with macrodef or scriptdef) from PAnt, not just the ones that come with Ant, so PAnt can complement any Ant extension library.
Cheers,
Posted by Alexander Ananiev April 8th, 2008 at 10:58 pmAlexander.