1. Introduction
While working in Java, there are times when we need to use multiple language versions at the same time.
It’s common to need our Java program to be compile-time compatible with one Java version (say – Java 6) but to need to use a different version (say – Java 8) in our development tools and a maybe different version to run the application.
In this quick article, we’ll demonstrate how easy it is to add Java version-based incompatibility safeguards and how the Animal Sniffer plugin can be used to flag these issues at build time by checking our project against previously generated signatures.
2. Setting -source and -target of the Java Compiler
Let’s start with a hello world Maven project – where we’re using Java 7 on our local machine but we’d like to deploy the project to the production environment which is still using Java 6.
In this case, we can configure the Maven compiler plugin with source and target fields pointing to Java 6.
The “source” field is used for specifying compatibility with Java language changes and “target” field is used to for specifying compatibility with JVM changes.
Let’s now look at Maven compiler configuration of pom.xml:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.12.1</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
With Java 7 on our local machine and Java code printing “hello world” to the console, if we go ahead and build this project using Maven, it will build and work correctly on a production box running Java 6.
3. Introducing API Incompatibilities
Let’s now look at how easy it is to introduce API incompatibility by accident.
Let’s say we start working on some new requirement and we use some API features of Java 7 which were not present in Java 6.
Let’s look at the updated source code:
public static void main(String[] args) {
System.out.println("Hello World!");
System.out.println(StandardCharsets.UTF_8.name());
}
java.nio.charset.StandardCharsets was introduced in Java 7.
If we now go ahead and execute the Maven build, it will still compile successfully but fail at runtime with linkage error on a production box with Java 6 installed.
The Maven documentation mentions this pitfall and recommends to use Animal Sniffer plugin as one of the options.
4. Reporting API Compatibilities
Animal Sniffer plugin provides two core capabilities:
- Generating signatures of the Java runtime
- Checking a project against API signatures
Let’s now modify the pom.xml to include the plugin:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>animal-sniffer-maven-plugin</artifactId>
<version>1.16</version>
<configuration>
<signature>
<groupId>org.codehaus.mojo.signature</groupId>
<artifactId>java16</artifactId>
<version>1.0</version>
</signature>
</configuration>
<executions>
<execution>
<id>animal-sniffer</id>
<phase>verify</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
Here, the configuration section of Animal Sniffer refers to an existing Java 6 runtime signature. Also, execution section checks and verifies the project source code against the given signature and flags if any issues are found.
If we go ahead and build the Maven project, the build will fail with the plugin reporting signature verification error as expected:
[INFO] ------------------------------------------------------------------------
[INFO] BUILD FAILURE
[INFO] ------------------------------------------------------------------------
[ERROR] Failed to execute goal org.codehaus.mojo:animal-sniffer-maven-plugin:1.16:check
(animal-sniffer) on project example-animal-sniffer-mvn-plugin: Signature errors found.
Verify them and ignore them with the proper annotation if needed.
5. Conclusion
In this tutorial, we explored the Maven Animal Sniffer plugin and how it can be used to report API related incompatibilities if any at build time.
As always, the full source code is available over on GitHub.