Agile Zone is brought to you in partnership with:

Julian writes by night as The Build Doctor, a poorly disguised non de plume. By day he is a freelance build engineer, systems administrator and all round useful guy. Julian lives near London with his fiance and children. He enjoys balancing a love of real ale and Indian food with cycling. Julian has posted 16 posts at DZone. View Full User Profile

Separation of concerns in Ant

04.23.2010
| 5996 views |
  • submit to reddit

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" />
</project>

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>
<target name="deploy" depends="tomcat:deploy" />

</project>

.. 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>
<target name="deploy" depends="jboss:deploy" />

</project>

… 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)

 

References
Published at DZone with permission of its author, Julian Simpson. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Himanshu Gupta replied on Fri, 2010/04/23 - 11:11am

Ya this is a nice approach to keep the build files maintainable. I remember writing a build files which will make four jar files and also an EJB client jar and packaging them all into an EAR and deploying to a remote server after executing all the test cases. At first I was writing all targets in one file but later I separated them. Thanks for this article.

Steven Baker replied on Sun, 2010/04/25 - 2:56am

This is a very slippery slope. It doesnt take much for your ant build to get out of hand and only a couple (if your lucky) devs know their way around it. I've seen this far too many times... This is where a convention based build starts to work wonders.

Julian Simpson replied on Mon, 2010/04/26 - 3:59pm

@Himanshu, glad you liked the article.

@Steven - I agree that Ant builds should be simple. People would be best with very simple builds, by convention. It's often very hard to back it out. But you can slowly tease them into shape.

Sindy Loreal replied on Sat, 2012/02/25 - 8:49am

I think this is over complicated.

Why not simply name the targets deploy and be done with it. All targets are entered into Ant dispatch under two names: for example the tomcat project would have one target named deploy and tomcat.deploy. So if you included both the tomcat and jboss projects you would have three target names in the dispatch tomcat.deploy, jboss.dispatch and dispatch; the entry named dispatch would point to the last loaded project's target dispatch.

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.