Build Number

One of the most important thing during the SDLC (for sure apart from the other stuff) is to keep control over deployed artifacts to all environments at any given time. Lack of control leads to chaos and generates a lot of extra work to the team, degrades throughput, morale and motivation. No need to even mention that arguments among team members regarding deployed features or fixes definitely do not contribute well to the team spirit.
One of the common approaches mitigating this risk is generating a build number to every single build fully automatically. Let’s take a look at how to accomplish this in common project set up – maven project build on build server e.g. TeamCIty. Sample web application follows.
Common place where to store such kind of info is MANIFEST.MF file. All kind of archives have this file located in /META-INF/MANIFEST.MF. Various technologies like OSGi use this location for various metadata. Taking advantage of maven-war-plugin the content of MANIFEST.MF can be easily customized as follows (${xx} are maven variables):
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Created-By: Apache Maven
Built-By: ${user.name}
Build-Jdk: ${java.version}
Specification-Title: ${project.name}
Specification-Version: ${project.version}
Specification-Vendor: ${project.organization.name}
Implementation-Title: ${project.name}
Implementation-Version: ${project.version}
Implementation-Vendor-Id: ${project.groupId}
Implementation-Vendor: ${project.organization.name}

To set up a maven project pom file is pretty easy:

         <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                            <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
                        </manifest>
                        <manifestEntries>
                            <Build-Number>${build.number}</Build-Number>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
        </plugins>

Where build.number variable gets supplied by build server in arbitrary format, e.g. for TeamCity build server:

Build number is visible in build queue status page as well:
To access these project build specific information simple jsp page can be created:
The controller accessing these information using Spring MVC (simplified example) can look like:
@Controller
 public class ProjectInfoController {

     @RequestMapping("/info")
     public ModelAndView getProjectInfo(HttpServletRequest request, HttpServletResponse response) throws IOException {

         ModelAndView modelAndView = new ModelAndView("projectInfoView");

         ServletContext servletContext = request.getSession().getServletContext();

         Properties properties = new Properties();
         InputStream is = servletContext.getResourceAsStream("/META-INF/MANIFEST.MF");

         properties.load(is);

         modelAndView.addObject("buildBy",properties.getProperty("Built-By"));
         modelAndView.addObject("buildJdk",properties.getProperty("Build-Jdk"));
         modelAndView.addObject("specificationVersion",properties.getProperty("Specification-Version"));
         modelAndView.addObject("specificationTitle",properties.getProperty("Specification-Title"));
         modelAndView.addObject("implementationVendor",properties.getProperty("Implementation-Vendor-Id"));
         modelAndView.addObject("buildNumber",properties.getProperty("Build-Number"));

         return modelAndView;
     }
 }

Accessing MANIFEST.MF in JAR file has a different approach. Motivation taken from Spring source code:

Package  package = someClass.getPackage( );
String version = package.getImplementationVersion();

JSP page or other presentation layer shouldn’t be a problem for anyone.

Advertisements