jakub holý

building the right thing, building it right, fast

Accessing An Artifact''s Maven And SCM Versions At Runtime

2013-05-22Tools

You can easily tell Maven to include the version of the artifact and its Git/SVN/... revision in the JAR manifest file and then access that information at runtime via getClass().getPackage.getImplementationVersion().

(All credit goes to Markus Krüger and other colleagues.)



Include Maven artifact version in the manifest



(Note: You will actually not want to use it, if you also want to include a SCM revision; see below.)

pom.xml:
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
...
<configuration>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
</manifest>
</archive>
</configuration>
...
</plugin>
</plugins>
</build>
...
</project>
view raw pom.xml hosted with ❤ by GitHub


The resulting MANIFEST.MF of the JAR file will then include the following entries, with values from the indicated properties:

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}


(Specification-Vendor and Implementation-Vendor come from the POM's organization/name.)

Include SCM revision



For this you can either use the Build Number Maven plugin that produces the property ${buildNumber}, or retrieve it from environment variables passed by Jenkins or Hudson (SVN_REVISION for Subversion, GIT_COMMIT for Git).

For git alone, you could also use the maven-git-commit-id-plugin that can either replace strings such as ${git.commit.id} in existing resource files (using maven's resource filtering, which you must enable) with the actual values or output all of them into a git.properties file.

Let's use the buildnumber-maven-plugin and create the manifest entries explicitely, containing the build number (i.e. revision)
<project>
<build>
<plugins>
<plugin>
<!-- Create the property $buildNumber holding the current Git revision -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<version>1.2</version>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
<configuration>
<doCheck>false</doCheck>
<doUpdate>false</doUpdate>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<manifestEntries>
<Implementation-Title>${project.name}</Implementation-Title>
<!-- buildNumber is produced at runtime by buildnumber-maven-plugin -->
<Implementation-Version>${project.version} ${buildNumber}</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
...
view raw pom.xml hosted with ❤ by GitHub


Accessing the version & revision



As mentioned above, you can access the manifest entries from your code via getClass().getPackage.getImplementationVersion() and getClass().getPackage.getImplementationTitle().

Pitfalls



According to some reports (), OpenJDK doesn't read the implementation version etc. attributes from a manifest. I have tried with OpenJDK 6 and 7 and it worked well.

References