{{ !articles[0].partner.isSponsoringArticle ? "Platinum" : "Portal" }} Partner
java,agile,ant,tools & methods

Separation of concerns in Ant

There’s nothing wrong with Ant. No, really! True, there’s some nasty Ant files out there. Perhaps that’s because we often treat our build as a second class citizen. How do you keep your build files from becoming bloated and hard to maintain? Break ‘em up!

I’m going to use a classic problem to illustrate this: deployment. Have you seen an Ant build that seemed to know far too much about the innards of the container? First you end up with a lot of properties. Then you need to maintain loads of odd targets to try and make it all work together. We can do better.

Step 1: Break it out. You want to have a totally separate Ant buildfile that you can use for deployment. Acceptance criteria: You can kick off a deploy by calling the separate file with a few properties (like where the deployable is, etc.)

Step 2: Import it. Use Ant’s import task in the body of your buildfile. Never inside a task!

Step 3: Prefix. A colon is a legal character in an Ant property or task name. So make the prefix match the name of the project. Each distinct buildfile should have the name attribute of the project element set with a meaningful name. Use that.

Step 4: Maintain discipline. It doesn’t matter how you do this. Cold showers, if you like. Just make sure that you keep the properties in the right place with the right name.

Here’s an example:

<project name="base" default="deploy">  
<property name="container" value="tomcat" description="The Java container that we use" />
<import file="${container}.xml" />

Note that there’s no deploy target in the file. That resides elsewhere. Running the default target will kick off a deploy to Tomcat from …

<project name="tomcat">

<property name="container:hostname" value="some.great.hostname" />
<property name="container:remote.user" value="deploy" />
<property name="tomcat:admin_url" value="http://${container:hostname}/admin" />

<target name="tomcat:deploy" description="This throws a war file at tomcat">
<echo message="gory details of tomcat deploy go here"/>
<target name="deploy" depends="tomcat:deploy" />


.. here. Note that there are properties with a nice generic prefix. Keep those generic because …

<project name="jboss">

<property name="container:hostname" value="some.great.other.hostname" />
<property name="container:remote.user" value="fleury" />
<property name="jboss:some.jboss.property" value="Paula is brilliant" />

<target name="jboss:deploy" description="This throws a war file at tomcat">
<echo message="jboss deploy goodness here"/>
<target name="deploy" depends="jboss:deploy" />


… all you need to do is pass a different container property to have it deploy elsewhere. What I love about this is that the two implementations cannot exist side-by-side. Only one can be imported, and the property namespace isn’t polluted.

(image thanks to Hansol)


Published at DZone with permission of {{ articles[0].authors[0].realName }}, DZone MVB. (source)

Opinions expressed by DZone contributors are their own.

{{ tag }}, {{tag}},

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}
{{ parent.authors[0].realName || parent.author}}

{{ parent.authors[0].tagline || parent.tagline }}

{{ parent.views }} ViewsClicks