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 works with Gradle 4 and 5 as shown in the table below:
Gradle |
Java runtime |
Source and target compatibility |
4.0+ |
7+ |
1.2+ |
5.0+ |
8+ |
1.6+ |
Note that your build can use Java 7 or 8, although it produces a modular jar. This is possible because the plugin assembles the module descriptors without using the java compiler.
Quick start
Put the following in your build.gradle
:
plugins {
id 'java'
id 'org.beryx.jar' version '1.2.0'
}
sourceCompatibility = 1.8
targetCompatibility = 1.8
To create your modular jar execute:
./gradlew jar
Usage
To make your library modular, you need to provide a module-info.java
in the project’s root source directory.
The plugin uses the JavaParser to analyze this file and
the ASM bytecode manipulation framework to generate the corresponding module descriptor.
This approach has the advantage that you don’t need a Java 9+ compiler to build your modular jar. The downside is that it cannot validate your module descriptor. References to nonexistent packages, modules, services, or service implementations go undetected.
Therefore, it is strongly advised to ensure the validity of your module descriptor by additionally building your
project using a Java 9+ compiler with the sourceCompatibility
and targetCompatibility
set accordingly.
The good news is that you don’t need to change your build script in order to do this.
The plugin lets you override the sourceCompatibility
and targetCompatibility
values by setting the
project property javaCompatibility
:
./gradlew -PjavaCompatibility=9 jar
Note that this project property overrides both sourceCompatibility
and targetCompatibility
with the same value.
If the plugin detects that at least one of sourceCompatibility
and targetCompatibility
has an effective value >= 9,
it automatically applies the gradle-modules-plugin, which adds support for the JPMS.
That’s why no changes are required to your build script when running in Java 9+ compatibility mode.
|
In the discussion above we considered that sourceCompatibility and targetCompatibility are
configured with pre-Java 9 values in build.gradle and you override them with 9+ values using the
javaCompatibility project property.You can also work the other way around: set sourceCompatibility and targetCompatibility with 9+ values
in build.gradle and override them with a pre-Java 9 value (via javaCompatibility ) in order to generate
a modular jar targeted to Java releases before 9.Both approaches have their pros and cons. Choose the one that suits you the most. |
Multi-release JAR
Typically, a modular jar
includes the module-info.class
file in its root directory.
This causes problems for some older tools, which incorrectly process the module descriptor as if it were a normal Java class.
To provide the best backward compatibility, the plugin creates by default a
modular multi-release jar
with the module-info.class
file located in META-INF/versions/9
, as shown below.
You can prevent the creation of a multi-release jar by setting multiRelease
to false
in the jar
section of your build script:
jar {
...
multiRelease = false
...
}
module-info.java location
As mentioned before, this plugin lets you create a modular jar even if you’re stuck with Java 7 or 8.
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 jar
section of your build script:
jar {
...
moduleInfoPath = 'src/main/module/module-info.java'
...
}
Examples
The following projects illustrate how to use this plugin to create modular jars targeted to pre-Java 9 releases:
-
badass-jar-example-nqueens: a Java library for solving the N-Queens problem.
-
badass-jar-example-nqueens-kotlin: a Kotlin library for solving the N-Queens problem.
Acknowledgements
This plugin was heavily inspired by and includes code from Gunnar Morling’s moditect tool.