Tag Archives: Maven

Displaying GIT build number (hash) in your REST API

The product i’m working on currently (a PaaS cloud offering) had a requirement to provide an API resource (GET call) throughout which a user could obtain basic details about the actual version of the API exposed (the api version, build time, corresponding git repo build number (hash id) and the jvm version used to compile the API). Except for the git repo hash part, everything else seemed to be quite easy to obtain. Below you’ll find the solution (step-by-step guide) i came up with.

 

End result (goal):

> curl http://api.my-system.company.com/1.0/
{
  "Implementation-Build" : "2951e7e",
  "Implementation-Build-Time" : "2013/09/17 12:40:02 AM,UTC",
  "Implementation-Jdk" : "1.7.0_15",
  "Implementation-Version" : "1.0-SNAPSHOT",
  "Implementation-Vendor" : "My Company, Inc.",
  "Implementation-Title" : "My System"
}

 

Technologies used:

 

Steps required: 

1. First let’s add the <scm> configuration tag to your master pom.xml file. The connection string represents the repository for which the buildnumber-maven-plugin will obtain the git hash id.

<scm>
    <!-- Replace the connection below with your project connection -->
    <connection>scm:git:git://github.com/mariuszprzydatek/hyde-park.git</connection>
</scm>

 

2. configure the maven-war-plugin to generate project’s MANIFEST.MF file, where the git hash id will be stored. Also, the Spring MVC controller will read this file in order to return its content as a result of GET call.

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.3</version>
    <configuration>
        <archive>
            <addMavenDescriptor>false</addMavenDescriptor>
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
            </manifest>
        </archive>
        <warName>1.0</warName>
    </configuration>
</plugin>

 

3. In the <properties> section of the pom we can define the format for the date timestamp that will be returned as the value of “Implementation-Build-Time” attribute.

<properties>
    <maven.build.timestamp.format>yyyy/MM/dd hh:mm:ss a,z</maven.build.timestamp.format>
</properties>

 

4. Next, let’s add the remaining pom sections that we’ll be storing in the MANIFEST.MF file for further read:

    <version>1.0-SNAPSHOT</version>
    <organization>
        <name>My Company, Inc.</name>
    </organization>
    <name>My System</name>

 

5. within the <archive> key of the maven-war-plugin <configuration> section, we need to add additional manifest entries including the one (<Implementation-Build>) that will be generated by the buildnumber-maven-plugin:

<archive>
    ...
    <manifestEntries>
        <Implementation-Build>${buildNumber}</Implementation-Build>
        <Implementation-Build-Time>${maven.build.timestamp}</Implementation-Build-Time>
    </manifestEntries>
</archive>

 

6. Add the buildnumber-maven-plugin itself which will do the hard work:

<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>buildnumber-maven-plugin</artifactId>
    <version>1.1</version>
    <executions>
        <execution>
            <phase>validate</phase>
            <goals>
                <goal>create</goal>
            </goals>
        </execution>
    </executions>
</plugin>

 

7. Finally, add the <configuration> section to the buildnumber-maven-plugin together with the <shortRevisionLength> key that is responsible for the length of git hash id we want to export:

<configuration>
    <shortRevisionLength>7</shortRevisionLength>
</configuration>

 

 

Now, let’s create the Spring MVC controller that will be handling the MANIFEST.FM file read and returning its content to the presentation layer.

@Controller
@RequestMapping
public class ApiController {

    /**
     * Handling GET request to retrieve details from MANIFEST.MF file
     * @return implementation details
     */
    @RequestMapping(method = RequestMethod.GET)
    public @ResponseBody Map<String, String> getBuildNumber(HttpServletRequest request) throws IOException {

        ServletContext context = request.getSession().getServletContext();
        InputStream manifestStream = context.getResourceAsStream("/META-INF/MANIFEST.MF");
        Manifest manifest = new Manifest(manifestStream);

        Map<String, String> response = new HashMap<>();
        response.put("Implementation-Vendor", manifest.getMainAttributes().getValue("Implementation-Vendor"));
        response.put("Implementation-Title", manifest.getMainAttributes().getValue("Implementation-Title"));
        response.put("Implementation-Version", manifest.getMainAttributes().getValue("Implementation-Version"));
        response.put("Implementation-Jdk", manifest.getMainAttributes().getValue("Build-Jdk"));
        response.put("Implementation-Build", manifest.getMainAttributes().getValue("Implementation-Build"));
        response.put("Implementation-Build-Time", manifest.getMainAttributes().getValue("Implementation-Build-Time"));

        return response;

    }

}

 

 

Hope you enjoyed this post.

Take care!