Thursday 5 November 2015

Show application version on your JSF screens

Introduction

Sometimes it can be handy to show the application version on the screen of your application. 
Users get used to have access to this information and it can also ease the communication in a lot of situations. Especially when you are releasing very often.
  • Users can see when a new version is available
  • When issues are reported, it is easier to indicate in which version it occurred
  • Refer to the version where a certain feature appeared in the application in the documentation.

In this text, I'll show you how you can create this version automatically with Maven and read and show it on a JSF screen.

Create version

Maven has support to put a timestamp and the project version in the manifest file. This file is  specifically designed to contain this kind of information (among other things).
You can configure the maven-war-plugin (this functionality is also available in the maven-jar-plugin) to put additional info in the manifest.mf file which is created by default.

<plugin>
   <artifactId>maven-war-plugin</artifactId>
   <version>2.4</version>
   <configuration>
      <failOnMissingWebXml>false</failOnMissingWebXml>
      <archive>
         <manifestEntries>
            <version>${project.version}</version>
            <buildTime>${maven.build.timestamp}</buildTime>
         </manifestEntries>
      </archive>
   </configuration>
   <goals>
      <goal>manifest</goal>
   </goals>
</plugin>

The format in which the timestamp is placed in the file can be environment specific, like local settings of your computer.
Therefor you should always define the timestamp format in the pom.xml file so that you have repeatable packaging between different environments.

The format can be specified by using a property like this.

<properties>
   <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
   <maven.build.timestamp.format>yyyyMMdd-HHmm</maven.build.timestamp.format>
</properties>

The result is that we have 2 entries in the manifest file, for example
buildTime: 20151104-1123
version: 1.0.2

Read the info

Reading the information is nothing specific for Java EE of JSF.  We will use the Properties file functionality to read the file.
A lot of people use the '=' sign as delimiter between the key and value pair in the file, but the semicolon (:) is also a default delimiter as you can read from this javadoc.

So if we have a reference to the manifest file, we can feed it in the load method of the properties class and we have the version and build time (as a string).
For this info, we can use the ServletContext and the resource loading which is available.

private Properties loadManifestFile() {
    ServletContext servletContext = (ServletContext) FacesContext
            .getCurrentInstance().getExternalContext().getContext(); 
      Properties prop = new Properties();
      try {
        InputStream resourceAsStream = servletContext.getResourceAsStream("/META-INF/MANIFEST.MF");  
         if (resourceAsStream != null) {
            prop.load(resourceAsStream);        }
    } catch (IOException e) {
        unexpectedTechnicalExceptionController.handleUnexpectedException(e); 
   }
    return prop;
}

As you can see in the above code, we need a reference to the FacesContext, so we need this code to be executed in the JSF context, like a @PostConstruct method of @ApplicationScoped CDI bean which keeps the version and build time, ready to shown it on a JSF screen.

Show the info

Showing the information is of course very specific for each application. And you would probably show it differently in each version.
In my last application, I showed the information  in a floating div in the bottom left area of the screen. That way, it was always visible.

<div style="position: fixed; bottom: 0; right: 0;">
   #{infoBean.version} (#{infoBean.buildTime})
</div>

Conclusion

With some easy configuration of maven, a simple read from the manifest file with the Properties class, we are able to show the version and built time of your application on screen. 
This can help in the good communication with your end users.
And of course, other information can be stored and used in a similar way.
Enjoy.