I have a need to change our current ant based build system from a single
monolithic build in which all utilities are part of the source tree of the
webapp currently under development into several component builds. This way
other web applications can share the same exact utilities, or more specifically
version X of each desired internal utility. To my knowledge there is no
combination of existing ant tasks (other than my custom task) that solve all of
the problems involved in a nice clean manner. Furthermore, I suspect most
every large company using ant with multiple teams will eventually encounter the
same problem set.
Componentizing the build solves the problem of sharing common libraries between
development teams. Unfortunately doing so also often causes the following
problems:
1) Some teams will inevitable end up using rather outdated versions of a shared
internal library.
2) Without an overall build system extending a utility can be rather cumbersome.
The general solution to potential problem 1 is to somehow increase the
visibility of a particular team's use of an outdated version. If upgrading to
a new version is easy enough (i.e. just edit a property file) and a team is
constantly reminded they are using an older version, they will likely tend to
stay up to date. Ideally the fact the team's code is using an old version will
be reported by any continuous integration environment (i.e. cruise-control).
Potential problem 2 is referring to the typical scenario in which one is
developing client code (a web application) to the internal utility when one
discovers the utility isn't adequate. In practice one is then often forced to
make changes to the utility, release a new version of the utility, configure
the client application to use the new version of the utility, see if the client
application's need has been satisfied and if not repeat the above steps. To
alleviate such tediousness one obviously tries to construct an overall build
environment that can compile/test/distribute the utility and then do the same
for the client application. In the event one is using such an overall build
the utility distribution that is created is simply a temporary one and probably
shouldn't represent an internal release. (When one completes extending the
utility one will most likely want to create an internal release.)
I found it very difficult to use the existing ant tasks to write an ant build
system that componentized the build system yet still addressed potential
problems 1 and 2. To that end I wrote a custom ant task that searches for each
desired utility and sets a class path reference with the results. The task
first searches an area intended for active build artifacts and failing that
looks for the desired release version in a specified directory. If a release
version is being used, the task reports at warning level if a newer version
exists. If an active build artifact is being used for a particular utility
then the task reports the fact at an info level. As well as the above
information, boundary cases indicating something is misconfigured result in
BuildExceptions being thrown.
The custom task only implements the missing functionality. It is still
expected the user will use the existing ant tasks to complete his/her overall
build environment.
Although only lightly documented the task is very thoroughly unit tested using
the Ant extensions to junit.
The task is currently adequate for my needs and I do not have the time to
submit it as a formal ant task. That said it would be in my employer's best
interest to have the ant team integrate it in as an official ant task (or just
a related project). To that end I believe I can get a formal legal release of
the code under an open-source license if there is any interest. The task is
useful in its current form (after someone writes a bit more documentation) but
could be made even more general than it is.
In case your wondering, I am intending to store our internal utility releases
in CVS in the same directory structure as expected by the custom ant task.
This will work fine for now, but at some future point may need to be done
differently.
The class level javadoc is copied below:
/**
* This ant task is intended to be used in determining
* where to acquire jar files for a given internal
* subproject.
*
* The search algorithm is as follows:
*
* Foreach subproject look in
* activebuildlibdir for a subproject.category
* directory. If found look for any jars there
* and add them to the path list.
* If unsuccessful then look in
* releasedir/subproject.category/subproject.desiredversion
* If nothing is found, get mad and throw a BuildException.
* If something is found see if the desired version
* is the most current version available
* in the releasedir/subproject.category directory.
* If you have trouble parsing the name
* of any subdirectory found
* in releasedir/subproject.category throw a BuildException.
* If the desired version is out of date
* log it at warning level.
*
* An example usage is shown below:
* <property name="subproject.lib.dir"
value="../subprojectactivebuildlib"/>
* <property name="release.dir" value="../internaltools"/>
* <property name="internal.core.category" value="core"/>
* <property name="internal.core.desiredversion" value="1_0_1"/>
* <property name="internal.db.category" value="db"/>
* <property name="internal.db.desiredversion" value="2_4_1"/>
*
* <!--After the below target's execution the subproject.classpath
* can be used as a refid for the classpath argument of the javac
* ant task -->
* <target name="determine.subproject.classpaths">
* <findsubprojects
* classpathid="subproject.classpath"
* activebuildlibdir="${subproject.lib.dir}"
* releaselibdir="${release.dir}">
* <subproject
* category="${internal.core.category}"
* desiredversion="${internal.core.desiredversion}"/>
* <subproject
* category="${internal.db.category}"
* desiredversion="${internal.db.desiredversion}"/>
* </findsubprojects>
*
* </target>
*
*/
Please let me know if you, the reader, are interested in more. (If you post
back to the mailing list, please send me an email as anything from the ant-dev
mailing list is automatically shuttled to its own directory and only
occasionally read.)
James Carpenter
[EMAIL PROTECTED]
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]