eHarmony Engineering logo

Enhancing RESTful Services with Manifest Data

David Gevorkyan

February 17, 2016

Enhancing your RESTful services with key environment metadata in your Manifest files is a core step towards creating a universal application status dashboard for all the API versions in all your environments. David Gevorkyan

One advantage of having RESTful services is enabling and advocating their use outside your team, especially since integration with RESTful APIs is so much easier than with traditional APIs (CORBA, SOAP). However, there’s definitely a cost to sharing your service’s capabilities, as you’ll see as soon as you’ve told other teams about your great service and they have started to use it.

Once the other engineering teams are using your RESTful service, you’ll immediately encounter the maintenance task of making sure that your documentation actually reflects the implementation of the API.

Hopefully by that time you already know that a common API Specification scheme exists (such as Swagger, or RAML, or Api Blueprint) and you are using it to serve consistent and interactive documentation (this topic alone is worthy of a separate blog post!)

Once you are at that stage, one thing that you might find missing from the above mentioned frameworks is information on your Hosted Artifact, such as:

  • Artifact version
  • Build date and time
  • Build JDK version
  • Build Maven version
  • Build OS version

I want to stress that this is not a replacement for API Specification frameworks, but rather an addition to them and can be implemented completely independently.

Luckily, enhancing an API with the details of Hosted Artifact can be achieved by leveraging MANIFEST.MF files, that are created during the compile time and can be used to surface all of these details during runtime to the client (through a RESTful endpoint).

This blog post explains how any type of information can be embedded through Manifest files, and that a variety of applications for this data exist.

Useful applications include:

  • Using the information during the CI / CD pipeline to ensure that the correct versions have been stood up.
    • Once that information is available in an automated manner, creating tools for syncing the environments becomes trivial.
  • Creating a visualization table of all environments and their corresponding Artifact versions – especially when you have multiple environments (LoadTest, Non-Production, Pre-Production, Production).
    • This is especially helpful for QA team, to ensure consistency between environments.
  • Debugging a particular issue becomes much easier when you have all of the details about the hosted artifact, such as a Listing of All Dependencies inside the  artifact, or OS Version might help even more.

Let’s look into some XML and Java code on how this can be done …

Manifest files are generally located under META-INF/MANIFEST.MF in your artifact (JAR, WAR, EAR), however they do not contain complete data. If you are using Maven for artifact creation, it can be easily enhanced with more entries as in the following Maven pom.xml example:

<!-- Example of embedding the Manifest inside JAR -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <version>2.4</version>
    <configuration>
        <archive>
            <!-- This is the config portion that does main work -->
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
            </manifest>
        </archive>
        <finalName>${project.artifactId}-${project.version}</finalName>
    </configuration>
</plugin>

<!-- Example of embedding the Manifest inside WAR -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.6</version>
    <configuration>
        <archive>
            <!-- This is the config portion that does main work -->
            <manifest>
                <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                <addClasspath>true</addClasspath>
            </manifest>
        </archive>
    </configuration>
</plugin>

The result of that will be a MANIFEST.MF file with the following content:

Manifest-Version: 1.0
Implementation-Title: match-service
Implementation-Version: 0.0.38-SNAPSHOT
Implementation-Vendor-Id: com.eharmony.elevatedcareers
Build-Jdk: 1.7.0_65
Built-By: dgevorkyan
Created-By: Apache Maven 3.2.1
Main-Class: com.eharmony.elevatedcareers.matchservice.MatchServiceAppl
 ication
Archiver-Version: Plexus Archiver

If data above is not enough, you can simply add extra custom entries using the following block in the maven-jar-plugin or maven-war-plugin:

<manifestEntries>
    <Java-Vendor>${java.vendor}</Java-Vendor>
    <Os-Name>${os.name}</Os-Name>
    <Os-Version>${os.version}</Os-Version>
</manifestEntries>

Once you have built the artifact with the manifest file, it is time to surface these details through the RESTful resource.

In our case, it looks something like this:


http://pathToOurService/v1.0/info

and yields a result that looks like:

{
    "manifest_version": "1.0",
    "implementation_title": "match-service",
    "implementation_version": "0.0.38-SNAPSHOT",
    "implementation_vendor_id": "com.eharmony.elevatedcareers",
    "built_by": "dgevorkyan",
    "build_jdk": "1.7.0_65",
    "created_by": "Apache Maven 3.2.1",
    "archiver_version": "Plexus Archiver"
}

Now imagine all of your services exposing these details. You could easily build a Dashboard to visualize the discrepancies for the deployed artifact between different environments, something like this:

Per-Environment-Dashboard

Looks intriguing, doesn’t it?

If you would like to implement this paradigm in your services, we have some good news for you …

We already created an Open Source library called Manifestor that contains generic code for reading manifest details as well as an implementation of Resource that you can embed inside your Jersey or Dropwizard service.

https://github.com/eHarmony/manifestor

The above mentioned use cases provide just a couple of applications of use. I’m sure that once engineers expose this data, Operations and QA teams will find even more use cases.