Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

State of Gradle Java 9 Support

DZone's Guide to

State of Gradle Java 9 Support

Love using Gradle but wonder how the build tool is adapting to Java 9? Check out the latest news for Jigsaw support and encapsulation.

· Java Zone ·
Free Resource

Verify, standardize, and correct the Big 4 + more– name, email, phone and global addresses – try our Data Quality APIs now at Melissa Developer Portal!

What Gradle Supports as of Version 4.2.1

As of Gradle 4.2.1, building and running Java applications using major distributions of JDK 9 such as Oracle JDK9, OpenJDK9, and Azul JDK9 is fully supported. Further, cross-compilation (built by JDK9 but runs on JDK8) is supported.

Some builds will break when upgrading to Java 9, regardless of build tool used. The Java team has made good and necessary changes to the JDK to facilitate better software architecture and security, but this has meant removing access to some APIs. Even if your project is ready, some tools and Gradle plugins have not yet been updated to work with Java 9.

There are no convenience methods for consuming and assembling Multi-Release JARs, but you can take a look at this MRJAR-gradle example if you want to use them.

Java Modules AKA Jigsaw Support

If you’re not yet familiar with the Java 9 Platform Module System, also known as Project Jigsaw, you should read Project Jigsaw: Module System Quick-Start Guide. The motivation and terminology are well explained in The State of the Module System.

A module is defined as “a named, self-describing collection of code and data” whereby packages are treated as code boundaries and are explicitly exported and required. Non-exported packages are not visible to module consumers, and furthermore, two modules cannot export the same packages, nor can they have the same internal packages. This means that packages cannot be “split” or duplicated between multiple modules, or compilation will fail.

Here is a guide that shows how to use Java modules with Gradle today. It walks you through the steps needed to tell Gradle to use the modulepath and not classpath when compiling Java sources and patch modules for testing purposes.

A bottom-up approach (converting libraries with no dependencies first) is recommended if you wish to incrementally convert to Java 9 modules. After all, modules are consumable as regular JARs. Be mindful of automatic modules when “legacy” JARs are added to the modulepath.

Achieving Encapsulation With the Java Library Plugin

One of the two major goals of the Java 9 module system is to provide better software architecture through strong encapsulation. Gradle 3.4 introduced the Java Library Plugin that enforces strong encapsulation for libraries by separating api dependencies (those meant to be exposed to consumers) from implementation dependencies whose internals are not leaked to consumers.

This, of course, does not eliminate the use of Java classpaths, another stated goal of Java modules. You can learn about the motivation and usage of the Java Library Plugin in this post. It’s worth noting that the Java Library Plugin is useful for projects using Java 7 and above — you do not need to migrate to Java 9 to have some stronger encapsulation.

Here’s what this means in practice, given this example library:

apply plugin: 'java-library'

name = 'mylibrary'
group = 'com.mycompany'

dependencies {
   api project(':model')
   implementation 'com.google.guava:guava:18.0'
}

Let’s presume we have an application that uses mylibrary.

public class MyApplication {
    
    public static void main(String... args) {
        // This does not compile using 'java-library' plugin
        Set<String> strings = com.google.common.collect.ImmutableSet.of("Hello", "Goodbye");
        
        // This compiles and runs
        Foo foo = com.mycompany.model.internal.Foo();
        
        // This also compiles and runs
        Class clazz = MyApplication.class.getClassLoader().loadClass("com.mycompany.model.internal.Foo");
        Foo foo = (Foo) clazz.getConstructor().newInstance();
    }
}

You can see that you get some of the benefits by adopting the Gradle’s Java Library plugin. If you are migrating to Java modules, you can use this rough mapping:

  • implementation dependency => requires module declaration
  • api dependency => requires transitive module declaration
  • runtimeOnly dependency => requires static module declaration

Next Steps

Stay tuned for updates on first-class Java modules support in Gradle.

You can use the Building Java 9 Modules guide to learn how to use Java modules with Gradle today.

Developers! Quickly and easily gain access to the tools and information you need! Explore, test and combine our data quality APIs at Melissa Developer Portal – home to tools that save time and boost revenue. Our APIs verify, standardize, and correct the Big 4 + more – name, email, phone and global addresses – to ensure accurate delivery, prevent blacklisting and identify risks in real-time.

Topics:
java ,gradle ,java 9 ,encapsulation ,plugins

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}