Skip to content

Create modular jars that target a Java release before 9

License

Apache-2.0, Unknown licenses found

Licenses found

Apache-2.0
LICENSE
Unknown
license-header.txt
Notifications You must be signed in to change notification settings

beryx/badass-jar-plugin

Repository files navigation

PRs Welcome License Build Status

Badass Jar Plugin

This plugin lets you seamlessly create modular jars that target a Java release before 9. This way, your library can be used not only by people who build JPMS applications, but also by people who are still using Java 8 or older releases.

Prerequisites

The plugin requires Gradle 7.1 or newer. For older Gradle releases you can use version 1.2.0 of this plugin.

Note that your build can create a modular jar even when using a Java 7 or 8 toolchain. This is possible because in this case the plugin assembles the module descriptors without using the java compiler.

Usage

To use the plugin, include the following in your build script:

plugins {
    id 'java'
    id 'org.beryx.jar' version '2.0.0'
}

The plugin uses an extension named moduleConfig. The sample below shows a few configuration options.

moduleConfig {
    moduleInfoPath = 'src/main/module/module-info.java'
    multiReleaseVersion = 9
    version = project.version
}

Since all properties have default values, the moduleConfig block may be missing.

To make your library modular, you need to provide a module-info.java, which usually resides in the project’s main java source directory. If the version of your java toolchain is greater than 8, the plugin compiles this file using the java compiler. Otherwise, it uses the JavaParser to analyze the module-info.java file and the ASM bytecode manipulation framework to generate the corresponding module descriptor. Note that in this later case, the plugin cannot validate your module descriptor. References to nonexistent packages, modules, services, or service implementations go undetected.

Therefore, you should use a Java 9+ toolchain whenever it’s possible.

The properties provided by the moduleConfig extension are described below.

multiReleaseVersion: create a Multi-release JAR with a specific version

default value: -1 (the module-info.class is put in the root of the jar)

Typically, a modular jar includes the module-info.class file in its root directory. This may cause problems with some older tools, which incorrectly process the module descriptor as if it were a normal Java class. To avoid this, you can create a modular multi-release jar with the module-info.class file located in META-INF/versions/<number>, as shown below.

multi-release-jar

By setting the multiReleaseVersion property to a value greater than 0, the plugin will create a multi-release jar:

moduleConfig {
    multiReleaseVersion = 9
    ...
}

moduleInfoPath: configure module-info.java location

default value: src/main/java/module-info.java

As mentioned before, this plugin lets you create a modular jar even if you use a Java 7 or 8 toolchain. However, your IDE may complain about the presence of module-info.java in your source directory when using a pre-Java 9 compiler. To avoid this situation, you can tell the plugin to retrieve the module descriptor from another location. You do this by setting the moduleInfoPath property in the moduleConfig extension:

moduleConfig {
    moduleInfoPath = 'src/main/module/module-info.java'
    ...
}

You should avoid using property when using a java toolchain with a version >= 9.

version: configure module version

default value: empty (no module version will be set)

You can specify a version for your module by setting the version property in the moduleConfig extension:

moduleConfig {
    version = '2.3.4'
    ...
}

neverCompileModuleInfo: always use JavaParser and ASM to assemble the module descriptor

default value: false

By default, if the version of your java toolchain is greater than 8, the plugin uses the java compiler to assemble a module descriptor from the module-info.java file. In some cases this may fail because the plugin is not able to determine all the compiler and jvm settings required for a JPMS build. A typical example is a project that uses Kotlin. In this case, you can set neverCompileModuleInfo to true in order to instruct the plugin to create the module descriptor using the JavaParser and the ASM library instead of the compiler.

moduleConfig {
    neverCompileModuleInfo = true
    ...
}

Examples

The following projects illustrate how to use this plugin to create modular jars targeted to pre-Java 9 releases:

Projects using badass-jar-plugin

Alternatives

Instead of this plugin you can use the gradle-modules-plugin with the modularity.mixedJavaRelease option. Choose the solution that best suits your needs.

Acknowledgements

This plugin was heavily inspired by and includes code from Gunnar Morling’s moditect tool.