Track every Build Number with Maven

Problem

You need to differentiate between build numbers. For example, you’ve just redeployed your application and need to ensure that the new version is what you are viewing. Or, you need to keep track of how many times you build. There could be many reasons why you want to know the build number that you are on. I use it for reporting bugs against specific builds.

Solution

maven-buildnumber-plugin. This Maven2 plugin will generate a unique build number each time your build your project. You can even configure which maven phase triggers the increment of the number. This plugin can also fetch data from SVN to ensure that a team of developers all get unique build numbers.

As a bonus, it generates a buildNumber.properties file so that you can read in this build number from anywhere in your project. Here is how I use the plugin.

First, update your pom.xml. You need to setup the build trigger.


<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>buildnumber-maven-plugin</artifactId>
      <version>1.0-beta-3</version>
      <executions>
        <execution>
          <phase>validate</phase>
          <goals>
            <goal>create</goal>
          </goals>
        </execution>
      </executions>
      <configuration>
        <doCheck>true</doCheck>
        <doUpdate>false</doUpdate>
        <format>${version}.{0,number}</format>
        <items>
          <item>buildNumber0</item>
        </items>
      </configuration>
    </plugin>
  </plugins>
</build>





Now, you’ll need the build number and append it to your artifact’s final name. Add this to your pom.xml

<build>
  <finalName>
    ${project.artifactId}-${project.version}.{buildNumber}
  </finalName>
</build>

Now you’re package goal will output a file named

projectname-1.0.1.war

This is a great start and now you can differentiate each and every build. However, I need to take this a step further.

I need to see the version on my application’s index page. To do this, I use an ant filter to write the version and timestamp to a version.html file, and then copy it to my project’ web app directory. Add this to your pom.xm.

<build>
  <plugins>
    <plugin>
      <artifactId>maven-antrun-plugin</artifactId>
      <executions>
        <execution>
          <phase>compile</phase>
          <configuration>
            <tasks>
              <!-- versioning -->
              <echo message="[build version]"/>
              <delete file="target/projectname/version.html"/>
              <tstamp>
                <format property="rightNow" pattern="d MMM yyyy" locale="en"/>
              </tstamp>
              <copy todir="target/projectname">
                <fileset dir="src/main/webapp">
                  <include name="version.html"/>
                </fileset>
                <filterset>
                  <filter token="VERSION" value="${buildNumber}"/>
                  <filter token="BUILTON" value="${rightNow}"/>
                </filterset>
              </copy>
              <echo message=" version is ${buildNumber}"/>
            </tasks>
          </configuration>
          <goals>
            <goal>run</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

Version.html is simple.

<p class="version">Version: @VERSION@</p>
<p class="built">Built on: @BUILTON@</p>

Finally, in my index page…

<jsp:include page="/version.html"/>

Almost everything you want to know about this plugin can be found on the plugin’s site: http://mojo.codehaus.org/buildnumber-maven-plugin/

Alternatives

As an alternative to writing and importing version.html, you can read buildNumber.properties in an MVC controller and put the version in your page model. This is what I for my login pages. I use a java class to read the build number, format it, and cache it. I start the first build number at 00100, then format that to 0.1.0. So the next build is 00101 which gets displayed as 0.1.1.





Update:Tips

Here is a usage tip. You can move the create goal into a build profile so that the build number only increments in specific situations. I use a profile for my Continuous Integration builds so that our version increments only when Hudson builds our apps. This also makes it possible to synchronize our Hudson build numbers to our module versions.

Feedback

What do you use to track build numbers? How do your format it?

Share

New and Unknown Java Libraries

I like finding new useful java libraries. I usually find them from posts like this one. Other times I find them because I have a problem needing a solution. Here are some of my favorite unknown java libraries that I have found over the past year. Today I use every one of these in my projects. Interestingly, 4 of 6 are hosted on http://code.google.com.

Google-API-Translate-Java

Provides a simple, unofficial, Java client API for using Google Translate.  I use this to translate caption files for videos into several other languages. It has lots of options and has never failed me.

XmlTool

XMLTool is a very simple Java library to be able to do all sorts of common operations with an XML document with a very easy to use class using the Fluent Interface pattern to facilitate XML manipulations.

XStream

XStream is a simple library to serialize objects to XML and back again. Also useful for creating JSON responses.

Architecture Rules

Architecture Rules leverages an xml configuration file and optional programmatic configuration to assert your code’s architecture via unit tests or ant tasks. This test is able to assert that specific packages do not depend on others and is able to check for and report on cyclic dependencies among your project’s packages and classes. Get cyclic dependency detection with the Maven 2 plugin and zero configuration.

CyberNeko HTML Parser

NekoHTML is a simple HTML scanner and tag balancer that enables application programmers to parse HTML documents and access the information using standard XML interfaces. This can be used to extract the textual content from an HTML fragment.

Charts4j

charts4j is a free, lightweight charts & graphs Java API. It enables developers to programmatically create the charts available in the Google Chart API through a straightforward and intuitive Java API.

What do you use?

Do you have any new and unknown java tools that you use that you would recommend we checkout?

Share

PropertyPlaceholderConfigurer with Default Values

My current project relies heavily on Spring. We use the PropertyPlaceholderConfigurer so that our application contexts can pull values from the properties files and inject them into our beans. This is all very common. This means when the beans are being created and a value like ${someproperty} shows up, the BeanFactory visits the configured properties files to find the value for someproperty and injects that value into the bean.

The problem arises when a bean is configured using such a placeholder but the requested property is not found. This causes our application to fail to start.

Our solution was to extend PropertyPlaceholderConfigurer to provide default values. These default values are loaded before loading any properties files.  Firs well glance over the java class.

import java.io.IOException;
import java.util.Properties;
import java.util.Map;
import java.util.HashMap;

public class DefaultPropertyPlaceholderConfigurer
        extends org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
{
  private Map<String, String> startingProperties = new HashMap<String, String>();

  public void setStartingProperties(Map<String, String> startingProperties)
  {
     this.startingProperties = startingProperties;
  }

  public DefaultPropertyPlaceholderConfigurer()
  {
      try
      {
          loadDefaultProperties();
      }
      catch (IOException e)
      {
          logger.warn("failed to load default properties", e);
      }
  }
   private void loadDefaultProperties()
          throws IOException
  {
      final Properties defaultProperties = new Properties();
       for(Map.Entry<String,String> entry : startingProperties.entrySet())
      {
          defaultProperties.put(entry.getKey(), entry.getValue());
      }
       this.setPropertiesArray(new Properties[]{defaultProperties});
  }
}

And the XML bean definition for our new PropertyPlaceholderConfigurer.

  <bean id="propertyConfigurer"
        class="app.factory.config.DefaultPropertyPlaceholderConfigurer">
      <property name="ignoreUnresolvablePlaceholders" value="true" />
      <property name="startingProperties">
          <map>
              <entry key="one.two.three" value="123" />
          </map>
      </property>
      <property name="locations">
          <list>
              <value>/WEB-INF/classes/preferences.properties</value>
          </list>
      </property>
  </bean>

So now, when one.two.three is not included in the properties file preferences.properties the value will be initialized to 123. The value is defined in the properties file, the default value of 123 is overridden with the custom value.

Use Case

Here are the details on our specific use case. We release updates that add new properties, however, in order for the user to run the updates, the application has to start first (it is a web application). If the property is not set then the BeanFactory fails to start the application because it can not resolve the placeholder. So the software can’t start without running the updates first, but the updates can not be run until the application is started.

Now the web application starts and uses the default value, the administrator can run the updates which add the custom values to the preferences.properties file, and the user is prompted to restart the software after the updates are complete. The restart is required to read the new values into the bean.

Oops

While I was writing this post I realized that there was a much simpler way to provide default properties without extending the base class.

Any ideas as to how I could have done it?

Share