ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
Subject cvs commit: jakarta-ant/docs ant_in_anger.html
Date Thu, 11 Jan 2001 11:56:36 GMT
donaldp     01/01/11 03:56:35

  Added:       docs     ant_in_anger.html
  Good docs to the recue !!!
  Submitted By: "Steve Loughran" <>
  Revision  Changes    Path
  1.1                  jakarta-ant/docs/ant_in_anger.html
  Index: ant_in_anger.html
  	Ant in Anger
  <body bgcolor="#FFFFFF" text="#000000">
  <h1 align="center">Ant in Anger:
  <h2 align="center">
  	Using Ant in a Production Development System
  <h4  align="center">
  Steve Loughran (<a href=""></a>)
  <a name="introduction">
  <a href="">Ant</a>
   can be an invaluable tool in a team development process -or it can
  be yet another source of problems in that ongoing crises we call
  development . This
  document contains some strategies and tactics for making the most of
  ant. It is moderately frivolous in places, and lacks almost any actual
  examples of ant xml. The lack of examples is entirely deliberate -it
  keeps document maintenance costs down. Most of the concepts covered
  don't need the detail about XML representations, as it is processes we
  are concerned about, not syntax. Finally, please be aware that the
  comments here are only suggestions which need to be customised to meet
  your own needs, not strict rules about what should and should not be
  Firstly, here are some assumptions about the projects which this
  document covers
  <li> Pretty much pure Java.
  <li> Team efforts, usually with the petulant prima-donnas all us Java
  programmers become once we realise how much in demand we are.
  <li> A fairly distributed development team -spread across locations and
  maybe time zones.
  <li> Separate sub projects -from separate beans in a big
  enterprise application to separate enterprise applications which need to
  be vaguely aware of each other.
  <li> Significant mismatch between expectations and time available to
  deliver. 'Last Week' is the ideal delivery date handed down from above,
  next century the date coming up from below.
  <li> Everyone is struggling to keep up with platform and tool evolution.
  <li> Extensive use of external libraries, both open and closed source.
  What that all means is that there is no time to spend getting things
  right, you don't have that tight control on how the rest of the team
  works and the development process is often more one of chaos minimisation
  than anything else. The role of ant in such projects is to ensure that
  the build, test and deploy processes run smoothly, leaving you with all
  the other problems.
  <a name="core">
  <h2>Core Practices</h2>
  Clarify what you want ant to do</h3>
  Ant is not a silver bullet. It is just another rusty bullet in the armory of
  development tools available at your disposal. Its primary purpose is to
  accelerate the construction and deployment of Java projects. You could certainly
  extend ant to do anything Java makes possible -it is easy to imagine writing an
  image processing task to help in web site deployment by shrinking and
  recompressing jpeg files, for example. But that would be pushing the boundary of
  what ant is really intended to do -so should be considered with care.
  Ant is also a great adjunct to an IDE -a way of doing all the housekeeping of
  deployment and for clean, automated builds. But a good modern IDE is a
  productivity tool in its own right -one you should consider keeping using. Ant
  just lets you give the teams somewhat more freedom in IDE choice -&quot;you can
  use whatever you want in development, but ant for the deployment
  Define standard targets
  When you have multiple sub projects, define a standard set of targets.
  Projects with a split between interface and implementation jar files
  could consider <b>impl</b> and <b>intf</b> targets -with separate
  <b>debug-impl</b>and <b>debug-intf</b> targets for the debug version.
  And of course, the ubiquitous <b>clean</b> target.
  With standard target names, it is easy to build encompassing ant build
  files which just hand off the work to the classes below using the
  <a href="index.html#ant">ant</a>
  task. For example. the clean target could be handed down to the intf and
  impl subdirectories from a parent directory
  <pre>&lt;target name=&quot;clean&quot;  depends=&quot;clean-intf,
  &lt;target name=&quot;clean-intf&quot; &gt;
  	&lt;ant dir=&quot;intf&quot; target=&quot;clean&quot; /&gt;
  &lt;target name=&quot;clean-impl&quot;&gt;
  	&lt;ant dir=&quot;impl&quot; target=&quot;clean&quot; /&gt;
  &lt;/target&gt;  </pre>
  	Extend ant through new tasks
  If ant does not do what you want, you can use the
  <a href="index.html#exec">exec</a> and
  <a href="index.html#java">java</a> tasks or
  <a href="index.html#script">inline scripting</a> to extend it. In a
  project with many build.xml files, you soon find that having a single
  central place for implementing the functionality keeps maintenance
  overhead down. Implementing task extensions through java code seems
  extra effort at first, but gives extra benefits:-
  <li>Cross platform support can be added later without changing any
  build.xml files</li>
  <li>The code can be submitted to the ant project itself, for other
  people to use and maintain</li>
  <li>It keeps the build files simpler</li>
  Embrace Automated Testing
  <b>(alternatively "recriminate early, recriminate often")</b>
  Ant lets you call <a href="junit.html">JUnit</a> tasks, which unit test
  the code your team has written. Automated testing may seem like extra
  work at first, but JUnit makes writing unit tests so easy that you have
  almost no reason not to. Invest the time in learning how to use
  JUnit, write the test cases, and integrate them in a 'test' target from
  ant so that your daily or hourly team build can have the tests applied
  Once code fetches from the code control system are added as another ant
  target, the integration test code can be a pure ant task run on any box
  dedicated to the task. This is ideal for verifying that the build and
  unit tests work on different targets from the usual development
  machines. For example, a Win95/Java1.1 combination could be used even
  though no developer would willingly use that configuration given the
  System tests are harder to automate than unit tests, but if you can
  write java code to stress large portions of the system -even if the code
  can not run as JUnit tasks- then the <a href= "index.html#java">java</a>
  task can be used to invoke them. It is best to specify that you want a
  new JVM for these tests, so that a significant crash does not break the
  full build.
  <a name="crossplatform">
  Cross Platform Ant
  Ant is the best foundation for cross platform Java development and
  testing to date. But if you are not paying attention, it is possible to
  produce build files which only work on one platform -or indeed, one
  single workstation.
  The common barriers to cross-platform ant are the use of command line
  tools (exec tasks) which are not portable, path issues, and hard coding
  in the location of things.
  <h3>Command Line apps: <a href="index.html#exec">Exec</a>/ <a href=
  The trouble with external invocation is that not all functions are found
  cross platform, and those that are often have different names -DOS
  descendants often expect .exe or .bat at the end of files. That can be
  bad if you explicitly include the extension in the naming of the command
  (don't!), good when it lets you keep the unix and DOS versions of an
  executable in the same bin directory of the project without name
  clashes arising.
  Both the command line invocation tasks let you specify which platform
  you want the code to run on, so you could write different tasks for each
  platform you are targeting. Alternatively, the platform differences
  could be handled inside some external code which ant calls. This can be
  some compiled down java in a new task, or an external script file.
  <h3>Cross platform paths</h3>
  Unix paths use forward slashes between directories and a colon to
  split entries. Thus
  <i>"/bin/java/lib/xerces.jar:/bin/java/lib/ant.jar"</i> is
  a path in unix. In Windows the path must use semicolon separators,
  colons being used to specify disk drives, and backslash separators
  This difference between platforms (indeed, the whole java classpath
  paradigm) can cause hours of fun.
  Ant reduces path problems; but does not eliminate them entirely. You
  need to put in some effort too. The rules for handling path names are
  that 'DOS-like pathnames are handled', 'Unix like paths are handled'.
  Disk drives -'C:'- are handled on DOS-based boxes, but placing them in
  the build.xml file ruins all chances of portability. Relative file paths
  are much more portable. Semicolons work as path separators -a fact which
  is useful if your ant invocation wrapper includes a list of jars as a
  defined property in the command line. In the build files you may find it
  better to build a classpath by listing individual files (using location=
  attributes), or by including a fileset of *.jar in the classpath
  Note that DOS descended file systems are case insensitive (apart from
  the obscure aberration of the WinNT posix subsystem run against NTFS),
  and that Windows pretends that all file extensions with four or more
  letters are also three letter extensions (try DELETE *.jav in your java
  directories to see a disastrous example of this).
  Ant's policy on case sensitivity is whatever the underlying file system
  implements *VERIFY*, and its handling of file extensions is that *.jav does not
  find any .java files. The Java compiler is of course case sensitive -you can
  not have a class 'ExampleThree' implemented in "".
  Some tasks only work on one platform -<a href= "index.html#chmod">
  Chmod</a> being a classic example. These tasks usually result in just a
  warning message on an unsupported platform -the rest of the target's
  tasks will still be called. Other tasks degrade their functionality on
  platforms or Java versions. In particular, any task which adjusts the
  timestamp of files can not do so properly on Java 1.1. Tasks which can
  do that - <a href="index.html#get">Get<a>, <a
  href="index.html#touch">Touch</a> and <A href="index.html#unzip">
  Unjar/Unwar/Unzip</a> for example, degrade their functionality on
  Java1.1, usually resorting to the current timestamp instead.
  Finally, Perl makes a good place to wrap up Java invocations cross
  platform, rather than batch files. It is included in most Unix
  distributions, and is a simple download for <a href=
  ""> Win32 platforms from
  ActiveState</a>. A Perl file with .pl extension, with the usual Unix
  path to perl on the line 1 comment and marked as executable can be run
  on Windows, OS/2 and Unix and hence called from Ant without issues. The
  perl code can be left to resolve its own platform issues.
  <a name="team">
  <h2>Team Development Processes</h2>
  Even if each team member is allowed their choice of IDE/editor, or even
  OS, you need to set a baseline of functionality on each box. In
  particular, the JDKs and jars need to be in perfect sync. Ideally pick
  the latest stable Java/JDK version available on all developer/target
  systems and stick with it for a while. Consider assigning one person to
  be the contact point for all tools coming in -particularly open source
  tools when a new build is available on a nightly basis. Unless needed,
  these tools should only really be updated monthly, or when a formal
  release is made.
  Another good tactic is to use a unified directory tree, and add on extra
  tools inside that tree. All references can be made relative to the tree.
  If team members are expected to add a directory in the project to their
  path, then command line tools can be included there -including those
  invoked by ant exec tasks. Put everything under source code control and
  you have a one stop shop for getting a build/execute environment purely
  from CVS or your equivalent.
  <a name="deploying">
  <h2>Deploying with Ant</h2>
  One big difference between ant and older tools such as make is that the
  processes for deploying java to remote sites are reasonably well
  evolved in ant. That is because we all have to do it these days, so
  many people have put in the effort to make the tasks easier.
  Ant can <a href="index.html#jar">Jar</a>, <a href= "index.html#tar">
  Tar</a> or <a href="index.html#zip">Zip</a> files for deployment, while
  the <a href="index.html#war">War</a> task extends the jar task for
  better servlet deployment. <a href = "jlink.html" >Jlink</a> is a jar
  generation file which lets you merge multiple sub jars. This is ideal
  for a build process in which separate jars are generated by sub
  projects, yet the final output is a merged jar. <a href=
  "index.html#cab">Cab</a> can be used on Win32 boxes to build a cab file
  which is useful if you have to target IE deployment.
  The <a href = "index.html#ftp">ftp</a> task lets you move stuff up to a
  server. Beware of putting the ftp password in the build file -a property
  file with tight access control is slightly better. The <a href=
  "index.html#fixcrlf">FixCRLF task</a> is often a useful interim step if
  you need to ensure that files have unix file extensions before upload. A
  WebDav task has long been discussed, which would provide a more secure
  upload to web servers, but it is still in the todo list. If DAV is your
  required upload mechanism, why not take up the challenge?
  EJB deployment is aided by the <a href="ejb.html">ejb tasks</a>. At the
  time of writing, only WebLogic was supported with these tasks -if your
  EJB server is not supported, extending the ejb tasks would benefit your
  project and the rest of the ant community.
  Finally, there are of course the fallbacks of just copying files to a
  destination using <a href="index.html#copy">Copy</a> and <a href =
  "index.html#copydir">Copydir</a> , or just sending them to a person or
  process using <a href= "index.html#mail">Mail</a>.
  <a name="directories">
  <h2> Directory Structures</h2>
  How you structure your directory tree is very dependent upon the
  project. Here are some directory layout patterns which can be used as
  starting points.
  <h3>Simple Project</h3>
  The project contains sub directories
  <table width="100%">
  	<td>common binaries, scripts -put this on the path.
  	<td>This is the tree for building; ant creates it and can empty it
  	in the 'clean' project.
  	<td>Distribution outputs go in here; the directory is created in ant
  	and clean empties it out
  	<td>Hand crafted documentation
  	<td>Imported Java libraries go in to this directory
  	<td>source goes in under this tree
  The bin, lib, doc and src directories should be under source code control.
  Slight variations include an extra tree of content to be included in the
  distribution jars -inf files, images, etc. Javadoc output can be
  directed to a doc/ folder beneath build/, or to doc/javadoc.
  <h3>Interface and Implementation split</h3>
  If the interface is split from the implementation code then this can be
  supported with minor changes just by having a separate build path for
  the interface directory -or better still just in the jar construction:
  one jar for interface and one jar for implementation.
  <h3>Loosely Coupled Sub Projects</h3>
  In the loosely coupled approach multiple projects can have their own
  copy of the tree, with their own source code access rights.
  One difference to consider is only having one instance of the bin and
  lib directories across all projects. This is sometimes good -it helps
  keep copies of xerces.jar in sync, and sometimes bad -it can update
  foundational jar files before unit testing is complete.
  To still have a single build across the sub projects, use parent
  build.xml files which call down into the sub projects.
  This style works well if different teams have different code
  access/commitment rights. The risk is that by giving extra leeway to the
  sub projects, you can end up with incompatible source, libraries, build
  processes and just increase your workload and integration grief all round.
  <h3>Integrated sub projects</h3>
  Tightly coupled projects have all the source in the same tree; different
  projects own different subdirectories. Build files can be moved down to
  those subdirectores (say src/com/iseran/core and src/com/iseran/extras),
  or kept at the top -with independent build files named core.xml and
  This project style works well if everyone trusts each other and the
  sub projects are not too huge or complex. The risk is that a split to a
  more loosely coupled design will become a requirement as the projects
  progress -but by the time this is realised schedule pressure and
  intertwined build files make executing the split well nigh impossible.
  If that happens then just keep with it until there is the time to
  refactor the project directory structures.
  <a name="antupdate">
  	Ant Update Policies
  Once you start using ant, you should have a policy on when and how the
  team updates their copies. A simple policy is "every official release
  after whatever high stress milestone has pushed all unimportant tasks
  (like sleep and seeing daylight) on the back burner". This insulates you
  from the changes and occasional instabilities that ant goes through
  during development. Its main disadvantage is that it isolates you from
  the new tasks and features that ant is constantly adding.
  Often an update will require changes to the build.xml files. Most
  changes are intended to be backwards compatible, but sometimes an
  incompatible change turns out to be
  necessary. That is why doing the update in the lull after a big
  milestone is important. It is also why including ant.jar and related
  files in the CVS tree helps ensure that old versions of your software
  can be still be built.
  The most aggressive strategy is to get a weekly or daily snapshot of the
  ant source, build it up and use it. This forces you to tweak the
  build.xml files more regulary, as new tasks and attributes can take
  while to stabilise. You really have to want the new features, enjoy
  gratuitous extra work or take pleasure in upsetting your colleagues to
  take this approach.
  Once you start extending ant with new tasks, it suddenly becomes much
  more tempting to pull down regular builds. The most recent ant builds
  are invariably the the best platform for writing your extensions, as you
  can take advantage of the regular enhancements to the foundational
  classes. It also prevents you from wasting time working on something
  which has already been done. A newly submitted task to do something
  complex such as talk to EJB engines, SOAP servers or just convert a text
  file to uppercase may be almost exactly what you need -so take it,
  enhance it and offer up the enhancements to the rest of the world. This
  is certainly better than starting work on your 'text case converter'
  task on Ant 0.8 in isolation, announcing its existence six months latter
  and discovering that instead of adulation all you get are helpful
  pointers to the existing implementation.
  You should also get on the <a href =
  "" > ant-dev mailing list
  </a>, as it is where the other developers post their work, problems and
  experience. The volume can be quite high: 40+ messages a day, so
  consider routing it to an email address you don't use for much else. And
  don't make everyone on the team subscribe; it can be too much of a
  <a name="tips">
  Tips and Tricks</h2>
  The <a href="index.html#get">get</a> task can fetch any URL, so be used
  to trigger remote server side code during the build process, from remote
  server restarts to sending SMS/pager messages to the developer
  Internationalisation is always trouble. Ant helps here with the <A href=
  "native2ascii.html">native2ascii</a> task which can escape out all non
  ascii characters into unicode. You can use this to write java files
  which include strings (and indeed comments) in your own non-ASCII
  language and then use native2ascii to convert to ascii prior to feeding
  through javac. The rest of i18n and l12n is left to you...
  Use Property Files
  Use external property files to keep per-user settings out the build
  files -especially passwords. Property files can also be used to
  dynamically set a number of properties based on the value of a single
  property, simply by dyamically generating the property filename from the
  source property. They can also be used as a source of constants across
  multiple build files.
  Faster compiles with Jikes
  The <a href="">jikes compiler</a> is usually much
  faster than javac, and does dependency checking. Get it. Then set
  build.compiler to "jikes" for it to be used in your build files.
  #include targets to simplify multi build.xml projects
  You can import XML files into a build file using &lt;?import?&gt;
  an element of XML syntax which the standard parsers use. This lets
  a multi-project development program share code through reference,
  rather than cut and paste re-use. It also lets one build up a file of
  standard tasks which can be reused over time. Because the import
  mechanism is at a level below which ant is aware, treat it as
  equivalent to the #include mechanism of the 'legacy' languages C and
  Implement complex Ant builds through XSL
  XSLT can be used to dynamically generate build.xml files from a source
  xml file, with the <a href="index.html#style">Style</a> task controlling
  the transform. This is the current recommended strategy for creating
  complex build files dynamically.
  Change the invocation scripts
  By writing your own invocation script -using the DOS, Unix or Perl
  script as a starting point- you can modify a ant behavior for an
  individual project. For example, you can use an alternate variable to
  ANT_HOME as the base, extend the classpath differently, or dynamically
  create a new command line property 'project.interfaces' from all .jar
  files in an interfaces directory.
  Having a custom invocation script which runs off a CVS controlled
  library tree under PROJECT_HOME also lets you control ant versions
  across the team -developers can have other copies of ant if they want,
  but the CVS tree always contains the jar set used to build your project.
  You can also write wrapper scripts which invoke the existing ant
  scripts. This is an easy way to extend them. The wrapper scripts can add
  extra definitions and name explicit targets, redefine ANT_HOME and
  generally make development easier. Note that "ant" in Windows is really
  "ant.bat", so should be invoked from another batch file with a "CALL
  ant" statement -otherwise it never returns to your wrapper.
  Write all code so that it can be called from Ant
  This seems a bit strange and idealistic, but what it means is that you should
  write all your java code as if it may be called as a library at some point in
  future. So do not place calls to <b>System.exit()</b> deep in the code -if you
  want to exit a few functions in, raise an exception instead and have
  <b>main()</b> deal with it.
  Use Antidote as the invocation tool
  Even if you edit ant files by hand, Antidote makes a good execution tool
  because it eliminates the startup time of the JVM, perhaps even some of
  the XML parsing delays. 
  <a name="puttingtogether">
  		Putting it all together
  What does an ant build process look like in this world? Assuming a
  single directory structure for simplicity, the build file
  should contain a number of top level targets
  <li>build - do an (incremental) build
  <li>test - run the junit tests
  <li>clean - clean out the output directories
  <li>deploy - ship the jars, wars, whatever to the execution system
  <li>publish - output the source and binaries to any distribution site
  <li>fetch - get the latest source from the cvs tree
  <li>docs/javadocs - do the documenation
  <li>all - clean, fetch, build, test, docs, deploy
  <li>main - the default build process (usually build or build & test)
  Sub projects 'web', 'bean-1', 'bean-2' can be given their own build
  files -web.xml, bean-1.xml, bean-2.xml- with the same entry points.
  Extra toplevel tasks related to databases, web site images and the like
  should be considered if they are part of the process.
  Debug/release switching can be handled with separate initialisation
  targets called before the compile tasks which define the appropriate
  Internal targets should be used to structure the process
  <li> init - initialise properties, extra-tasks, read in per-user
  property files.
  <li> init-debug - initialise debug properties
  <li> init-release - initialise release properties
  <li> compile - do the actual compilation
  <li> link/jar - make the jars or equivalent
  <li> staging - any pre-deployment process in which the output is dropped
  	off then tested before being moved to the production site.
  The switching between debug and release can be done using the 'if' and
  'unless' conditional flags on the targets, so that debug gets called
  unless 'project.mode.release' is defined.
  It is useful to define a project name property which can be echoed in
  the init task. This lets you work out which ant file is breaking in a
  multi file build.
  What goes in to the internal ant tasks depends on your own projects. One
  very important tactic is 'keep path redefinition down through
  references' - you can reuse paths by giving them an ID and then
  referring to them via the 'refid' attribute you should only need to
  define a shared classpath once in the file; filesets can be reused
  Once you have set up the directory structures, and defined the ant tasks
  it is time to start coding. An early priority must be to set up the
  automated test process, as that not only helps ensures that the code
  works, it verifies that the build process is working.
  And that's it. The build file shouldn't need changing as new source
  files get added, only when you want to change the deliverables or part
  of the build process. At some point you may want to massively
  restructure the entire build process, restructuring projects and the
  like, but even then the build file you have should act as a foundation
  for a split build file process -just pull out the common properties into
  a properties file all build files read in, keep the target names unified
  and keep going with the project. Restructuring the source code control
  system is often much harder work.
  <h2>The Limits of Ant</h2>
  Before you start adopting ant as the sole mechanism for the build
  process, you need to be aware of what it doesn't do.
  <h3>It's not a scripting language</h3>
  Ant lets you declare what you want done, with a bit of testing of the
  platform and class libraries first to enable some platform specific
  builds to take place. It does not let you specify how to handle things
  going wrong (a listener class can do that), or support complex
  conditional statements.
  If your build needs to handle exceptions then look at the sound listener
  as a simple example of how to write your own listener class. Complex
  conditional statements can be handled by having something else do the
  tests and then build the appropriate ant task. XSLT can be used for
  <h3>It's not Make</h3>
  Some of the features of make, specifically inference rules and
  dependency checking are not included in ant. That's because they are
  'different' ways of doing a build. Make requires you to state
  dependencies and the build steps, ant wants you to state tasks and the
  order between them, the tasks themselves can do depedency checking or
  not. A full java build using Jikes is so fast that dependency checking
  is relatively moot, while many of the other tasks (but not all), compare
  the timestamp of the source file with that of the destination file
  before acting.
  <h3>It's not meant to be a nice language for humans</h3>
  XML isnt a nice representation of information for humans. It's a
  reasonable representation for programs, and text editors and source code
  management systems can all handle it nicely. But a complex ant file can
  get ugly because XML is a bit ugly, and a complex build is, well,
  complicated. Use XML comments so that the file you wrote last month
  still makes sense when you get back to it, and use Antidote to edit the
  files if you prefer it. 
  Software development is meant to be fun. Being in the maelstrom of a
  tight project with the stress of integration and trying to code
  everything up for an insane deadline can be fun -it is certainly
  exhilirating. Adding a bit of automation to the process may make things
  less chaotic, and bit less entertaining, but it is a start to putting
  you in control of your development process. You can still have fun, you
  should just have less to worry about, a shorter build/test/deploy cycle
  and more time to spend on feature creep or important things like skiing.
  So get out there and have fun!
  <a name="reading">
  <h2>Further Reading</h2>
  Continuous Integration</a>; Martin Fowler. <br>
  A paper on using ant within a software project
  running a continuous integration/testing proces.
  <li> Refactoring; Martin Fowler, ISBN: 0201485672 <br>
  	Covers JUnit as well as tactics for making some headway with the mess of
  	code you will soon have.
  <p align="center">Copyright &copy; 2000 Apache Software Foundation. All rights

View raw message