Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Separation of concerns in Ant

DZone's Guide to

Separation of concerns in Ant

· Agile Zone ·
Free Resource

Adopting a DevOps practice starts with understanding where you are in the implementation journey. Download the DevOps Transformation Roadmap. Brought to you in partnership with Techtown.

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)

 

Take Agile to the next level with DevOps. Learn practical tools and techniques in the three-day DevOps Implementation Boot Camp. Brought to you in partnership with Techtown.

Topics:

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}