Version names with Maven: Reading the version name

The first article in this series – “Version names with Maven: Creating the version name” –shows how during the build, and with Maven’s help, a version number, enriched with further information can be written into a manifest, properties or HTML file. Based on the first article, this second one describes how it can be read from within the application. This is helpful in many cases: You can immediately see which version is deployed on which stage, the version information can avoid misunderstandings in error reports, etc.

In the following, the designation “version name” is used to name the version number which contains further information (such as build number, time stamp, branch and commit ID).

This article first of all provides a basic explanation on how to programmatically read the version name from the properties and manifest files with standard JDK tools. In order not to have to implement this once again in each application, this was extracted into a small and reusable library (please see versionName at Github). Using this, executable examples are shown in the further course of the process (Client application and web application, please see versionName/examples at GitHub).

Accessing the version names in the HTML file from source code is not necessary because this is written directly into the file during the build and then displayed directly on the client.

Reading version names from a properties file

The essential logic for the reading of the version name from the properties file looks like the following:

String getVersionNameFromProperties() throws IOException {
    String propertiesName = "/app.properties";

    InputStream propertiesStream = getClass().getResourceAsStream(propertiesName);
    if (propertiesStream != null) {
        Properties props = new Properties();
        props.load(propertiesStream);

        return props.getProperty("versionName");
    }
    return "";
}

Exception handling, closing of resources and null checks were omitted in this snippet in order to ensure a clear overview. In the library versionName, this is implemented in the method VersionNames.getVersionNameFromProperties(). Defensibly, it always gives back an instance of String (never null). In the event of an error, an empty string is given back. Error notifications are logged using SLF4J.

Reading version names from the manifest

Analogous to reading the version names from a properties file, reading from the manifest file looks like the following:

String getVersionNameFromManifest() throws IOException {
    InputStream manifestStream = getClass().getClassLoader().getResourceAsStream("META-INF/MANIFEST.MF");
    if (manifestStream != null) {
        Manifest manifest = new Manifest(manifestStream);
        Attributes attributes = manifest.getMainAttributes();
        return attributes.getValue("versionName");
    }
    return "";
}

In order to ensure a clear overview, exception handling etc. was also omitted in this snippet. In the library versionName, this is implemented in the method VersionNames.getVersionNameFromManifest(). Defensibly, this also always gives back an instance of String (never null) and logs error notifications using SLF4J.

Using the library versionName

In order to be able to read the version name using the library versionName, it needs to be on the classpath. The library is not available on the MavenCentral, yet. It can be used, however, via the JitPack repository, that is based on the GitHub code. It is specified in the pom.xml as follows:

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://jitpack.io</url>
    </repository>
</repositories>

Using this, the following dependency can be resolved:

<dependency>
    <groupId>com.github.triologygmbh.versionName</groupId>
    <artifactId>versionName</artifactId>
    <version>1.0.0</version>
</dependency>

Alternatively, the class VersionNames and the associated unit tests can be copied into the respective project.

Example of a client application

The easiest example to implement is a client application that is packed into a JAR file. Here the version names can be read from the manifest file as follows (please also see App.java):

public class App {
    public static void main(String[] args) throws IOException {
        System.out.println(VersionNames.getVersionNameFromManifest());
    }
}

If this class is compiled with dependencies and packed into a JAR file (please see example „jar“), it can be executed like so:

java -jar jar/target/jar-1.0.1-SNAPSHOT-jar-with-dependencies.jar

This leads, for example, to the following output

1.0.1-SNAPSHOT (2016-10-25T09:51:03Z, branch master, commit 0b2c7b2)

Example web application

When it comes to web applications it is recommendable to directly write the version names into a HTML file and display it on the client. This means that no programming access is required.

If the version name should be available on the server side, using a properties file recommends itself. From this, the version name can, for example, be made available as a JAX-RS resource (Please also see VersionResource.java):

@Path("version")
public class VersionResource {
    private static final String VERSION_NAME = VersionNames.getVersionNameFromProperties();

    @GET
    public String getVersion() {
        return VERSION_NAME;
    }
}

The example “war” shows a web application (packed into a WAR-file), that contains the VersionResource and the associated JAX-RS application class (please see RestApplication.java). Furthermore, the version name is written into a HTML and properties file during the build.

If this is compiled with dependencies and packed into a JAR file (please see example ”server“), which provides the WAR file on an embedded servlet container (e.g. Jetty), the JAR file can be executed like so:

java -jar server/target/server-1.0.1-SNAPSHOT-jar-with-dependencies.jar

Following successful execution of the command, both the HTML file that can be accessed via the URL http://localhost:8080, as well as the JAX-RS resource that can be accessed via the URL http://localhost:8080/api/version give back the following, for example:

1.0.1-SNAPSHOT (2016-10-25T09:51:03Z, branch master, commit 0b2c7b2)

Conclusion

In the first part this article series shows
• how to write the version name with Maven into various file types (manifest, properties, HTML),
• various options with which the version name can be expanded (build number, time stamp, branch and commit ID),
and in this second part,
• the general mechanism for reading the version name from these files with standard JDK tools,
• the use of the library versionName, which allows convenient reuse of this mechanism and
runnable examples (client and web applications), which integrate all these contents.

Share this article

Johannes Schnatterer
Solution Architect
With a special focus on quality, open source enthusiasm, a touch of pedantry and Boy Scout Rule under his belt, he is trying to make the world of IT a little better every day.