Fortunately, it's pretty easy to configure Ant to automatically inject the SVN version into your application every time you build it. Let's say that you have a particular file (/WEB-INF/jsp/admin.jsp) that should contain the SVN version number.
We take advantage of svntask, a nice simple library that lets Ant use SVN. Download/unzip the project files, place them somewhere convenient in your project, and add the following to your Ant build file: (modifying the fileset directory to where you put the svntask libraries)
<target name="version">
<typedef resource="com/googlecode/svntask/svntask.xml">
<classpath>
<fileset dir="${lib.dir}/buildtime">
<include name="svnkit.jar" />
<include name="svntask.jar"/>
</fileset>
</classpath>
</typedef>
<svn>
<info path="." revisionProperty="revisionVersion" />
</svn>
<property name="svn.version" value="${revisionVersion}" />
</target>
This stores the SVN version number of your project root in the "svn.version" Ant property. Now, it's just a matter of copying the correct file from the source web directory to the target web directory before you package your .war file: (The following will require some modification depending on how you normally package your wars.) We use Ant's copy/filter tasks to replace all occurances of the token "@version@" in admin.jsp with the SVN version number.
<target name="war.pre" depends="version">
<copy file="${src.web.dir}/WEB-INF/jsp/admin.jsp"
tofile="${target.war.expanded.dir}/WEB-INF/jsp/admin.jsp"
overwrite="true">
<filterset>
<filter token="version" value="${svn.version}" />
</filterset>
</copy>
</target>
Now, the following snippit in admin.jsp
<div id="footer">
<p>Build Number @version@</p>
</div>
becomes
<div id="footer">
<p>Build Number 1692</p>
</div>
This is good enough for production releases, where the package application will (or should) be compiled straight from the repository. However, during development, I often won't be checking in changes between builds. So, to tell those builds apart, I find it useful to include the build timestamp as well, which I can get using Ant's tstamp task. This isn't a perfect solution, but it's enough to give me some reassurance that I didn't accidentally deploy an old build to my local server.
<target name="war.pre" depends="version">
<tstamp>
<format property="war.tstamp" pattern="yyyy-MM-dd HH:mm:ss z" />
</tstamp>
<copy file="${src.web.dir}/WEB-INF/jsp/admin.jsp"
tofile="${target.war.expanded.dir}/WEB-INF/jsp/admin.jsp"
overwrite="true">
<filterset>
<filter token="version" value="${svn.version}" />
<filter token="time" value="${war.tstamp}" />
</filterset>
</copy>
</target>
Now, inside of admin.jsp, I can include the following snippit
<div id="footer">
<p>Build Number @version@ (@time@)</p>
</div>
and Ant will transform this into
<div id="footer">
<p>Build Number 1692 (2009-03-30 11:20:15 PDT)</p>
</div>
which is exactly what I want.
1 comments:
Here is another tip.
Put this inside your <jar></jar> in ant:
<manifest>
<attribute name="Specification-Version" value="${version}" />
<attribute name="Implementation-Version" value="${TODAY}" />
<attribute name="Main-Class" value="com.foo.Version" />
</manifest>
package.com.foo;
public class Version
{
/** */
public static String getSpecification()
{
Package pkg = Version.class.getPackage();
return (pkg == null) ? null : pkg.getSpecificationVersion();
}
/** */
public static String getImplementation()
{
Package pkg = Version.class.getPackage();
return (pkg == null) ? null : pkg.getImplementationVersion();
}
/**
* A simple main method that prints the version and exits
*/
public static void main(String[] args)
{
System.out.println("Version: " + getSpecification());
System.out.println("Implementation: " + getImplementation());
}
}
Then, you can do this:
java -jar my.jar
No need to put version numbers in jar files ever again. =)
You also get to easily do this:
/** @return all the version numbers */
public Package[] getVersions()
{
Package[] packages = Package.getPackages();
return packages;
}
Then in a jsp page:
<table>
<tr>
<th>Package</th>
<th>Version</th>
<th>Implementation</th>
</tr>
<c:forEach var="pkg" items="${backend.versions}">
<tr>
<td><c:out value="${pkg.name}"/></td>
<td><c:out value="${pkg.specificationVersion}"/></td>
<td><c:out value="${pkg.implementationVersion}"/></td>
</tr>
</c:forEach>
</table>
To get something like this:
http://subethamail.org/se/version.jsp
-jon (author of svntask and appreciative of the nice comments about his project)
Post a Comment