Combining Different Java Versions
Java8 was released in mid-March and the Java 7 End Of Life plan has already been announced. In a perfect world we would all be pushing forward with Java 8, but in reality, other requirements often get in the way. Many developers I talk to say that their production environments (or more likely, their customer’s production environments) are very conservative, and are not approved for Java 7 deployment yet, let alone Java 8.
But what if these conservative customers don’t use all your features? What if you package your system in many different ways for many different uses? Could the new features — which will not be deployed on your conservative customers systems — be developed with Java8? If you are using OSGi, then the answer is yes!
The key to this is the Execution Environment (EE). EEs are symbolic representations of Java Runtimes, and are relevant both at development time and run-time. For example, if a bundle only uses J2SE-1.6 (it doesn’t use any of libraries or language features of >= 1.7), it could specify this. At development time, the compiler will attempt to compile your bundle against the specified EE, and at runtime, OSGi would ensure that the proper execution environment is available to run your bundle.
This is even possible if you are not using OSGi at runtime, but you won’t get the runtime validation (you’ll have to manage this yourself during deployment).
OSGi provides excellent runtime modularity constructions. However, even if you don’t use OSGi at runtime, OSGi + Eclipse provides a very powerful way to structure your system at development time. OSGi bundles explicitly state their dependencies, and each bundle (module) can specify its Execution Environment.
In this example, we will use Java 7 to develop our core application and Java 8 for our tests. (Note: in practice, it’s probably a bad idea to run your tests on a different EE than your production environment, but that’s up to you).
The key is to create ‚Eclipse Plug-in Project‘ even if you have no intention of writing an Eclipse plug-in. This type of project really means OSGi bundle, or even more generally, a Java Project with an OSGi Manifest.
The OSGi Manifest is nothing more than a text file that provides additional metadata to your project. With this Manifest, you can now explicitly state the dependencies each project has, including the Execution Environment on which it runs. If you are not using an OSGi runtime, this Manifest will be ignored.
In this case, our simple Gumball machine will run on a Java 7 JRE, even if your developing and building on Java 8.
Now create a second project for your tests. Unlike standard Maven projects, Eclipse packages the tests separately. This allows you to specify a different set of dependencies (as well as a different Execution Environment) for your tests. In this case, we will target Java 8.
Eclipse will actually keep each project isolated so when you develop your Gumball Machine, all the quick-fixes, content-assists, refactoring options, etc… will be relevant for Java 7. This means you won’t accidentally introduce a Java 8 dependency into your core application. If you happen to write Java 8 specific code, Tycho will also fail to compile the project (assuming you have your toolschains.xml properly configured).
Furthermore, when you develop your tests, all the goodness of Java 8 will be at your fingertips.
Setting up a build for a Java 7 / Java 8 hybrid is fairly straightforward. In fact, Tycho will use the settings in your manifest to produce the proper class files if you set the useJDK == BREE the tycho-compiler-plugin configuration.
At the time this article was written, Tycho’s support for Java 8 has not been fully assembled. You need to grab the latest JDT from Eclipse.org and Tycho-Version 0.20.0. While this may sound complicated, it’s actually pretty easy. Simply use the following tycho-compiler dependencies in your top level POM.
Running The Build
Java 8 must be installed (and set as your default JDK) in order to run the build. However, the class files for your project will still run on a Java 7 JRE.
If you plan on using Jacoco coverage, make sure you have Version 0.7.0.201403182114, this version supports Java 8.
Getting the Code
The example used here (including the POM files, OSGi Manifests and Eclipse project configuration files) are all available on GitHub.