Multi Release JAR Maven Plugin

Enables building of multi-release JARs using Maven.

License

License

Categories

Categories

Maven Build Tools
GroupId

GroupId

pw.krejci
ArtifactId

ArtifactId

multi-release-jar-maven-plugin
Last Version

Last Version

0.1.5
Release Date

Release Date

Type

Type

maven-plugin
Description

Description

Multi Release JAR Maven Plugin
Enables building of multi-release JARs using Maven.
Project URL

Project URL

https://github.com/metlos/multi-release-jar-maven-plugin
Project Organization

Project Organization

Lukas Krejci
Source Code Management

Source Code Management

https://github.com/metlos/multi-release-jar-maven-plugin

Download multi-release-jar-maven-plugin

How to add to project

<plugin>
    <groupId>pw.krejci</groupId>
    <artifactId>multi-release-jar-maven-plugin</artifactId>
    <version>0.1.5</version>
</plugin>

Dependencies

compile (4)

Group / Artifact Type Version
org.apache.maven : maven-plugin-api jar 3.3.9
org.apache.maven.plugin-tools : maven-plugin-annotations jar 3.5
org.apache.maven.plugins : maven-compiler-plugin jar 3.7.0
org.apache.maven.plugins : maven-jar-plugin jar 3.0.2

provided (1)

Group / Artifact Type Version
org.apache.maven : maven-core jar 3.3.9

Project Modules

There are no modules declared in this project.

Multi Release JAR Maven Plugin

Warning
DO NOT USE THIS EXTENSION. It was meant as a quick hack to enable multi-release support in Maven until this is better supported in Maven itself. There is now a number of ways to construct multi-release jars, each of which is less hacky and more maintainable than this solution. Please consult https://maven.apache.org/plugins/maven-compiler-plugin/multirelease.html for more information.

Java 9 has been released but Maven still lacks support for multirelease JARs.

There are solutions to build them using existing Maven plugins (like this or this) but they all lack the flexibility and features of the standard maven compiler plugin.

This plugin is a quick and dirty solution to the current lack of tooling. It introduces a new packaging and a new source directory to build multi-release jars with the full feature set of the maven compiler plugin.

Getting Started

Note
For all this to work, you need to run Maven using Java 9.

First, you need to define this plugin as a build extension in your POM.

<build>
  <extensions>
    <extension>
      <groupId>pw.krejci</groupId>
      <artifactId>multi-release-jar-maven-plugin</artifactId>
      <version>...</version>
    </extension>
  </extensions>
  ...

Next, you need to change the packaging of your module to

<packaging>multi-release-jar</packaging>

And that’s it for the basic setup in pom.xml.

Now you need to actually add your sources for different java releases. For each java release, the corresponding sources should go into java-mr/<RELEASE-NUMBER>. E.g. for Java 9 you put the Java 9 specific sources into src/main/java-mr/9 directory.

Now when you compile the module, classes from src/main/java will be normally put into the jar while classes from src/main/java-mr/9 will end up in META-INF/versions/9 of the resulting jar.

Controlling Compilation

The multi-release-jar-maven-plugin compile goal has the same configuration properties as the classic maven-compiler-plugin.

To compile the main sources as Java 8, you need to configure it as you would the maven compiler plugin, i.e. either using properties maven.compiler.source and maven.compiler.target set to 1.8

<properties>
  <maven.compiler.source>1.8</maven.compiler.source>
  <maven.compiler.target>1.8</maven.compiler.target>
</properties>

or by configuring the plugin itself like so:

<build>
  <plugins>
    <plugin>
      <groupId>pw.krejci</groupId>
      <artifactId>multi-release-jar-maven-plugin</artifactId>
      <version>...</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</source>
      </configuration>
    </plugin>
    ...

To provide different configuration properties to the compiler when compiling for different than the default release, you can use:

<build>
  <plugins>
    <plugin>
      <groupId>pw.krejci</groupId>
      <artifactId>multi-release-jar-maven-plugin</artifactId>
      <version>...</version>
      <configuration>
        <perReleaseConfiguration>
          <release>9</release>
          <configuration>
            <compilerArguments>
              <arg>-Xlint</arg>
            </compilerArguments>
          </configuration>
        </perReleaseConfiguration>
      </configuration>
    </plugin>
    ...

The main configuration supports all properties of the maven compiler plugin but only a handful of properties can be modified for per-release compiler configurations:

Controlling Module Info

Module info class(es) can be located in any (or all) of the parts of the multi-release jar. If the main classes are compiled for Java 8, you cannot easily compile module-info.java together with the rest of the classes though you maybe would like to. Having a module-info.class in the root of the jar makes it a module by default. If you had the module-info.class only in one (or more) of the version directories, that module info would be valid only when run with the corresponding java version.

To compile for Java 8 by default but have a module-info.class also in the root of the jar, you can do the following:

<build>
  <plugins>
    <plugin>
      <groupId>pw.krejci</groupId>
      <artifactId>multi-release-jar-maven-plugin</artifactId>
      <version>...</version>
      <configuration>
        <source>1.8</source>
        <target>1.8</target>
        <mainModuleInfo>9</mainModuleInfo>
        ...
      </configuration>
      ...

Your module-info.java would be located in src/main/java-mr/9 but would end up compiled in the root of the jar after compilation and packaging instead of META-INF/versions/9 as it would without the mainModuleInfo configuration property.

Versions

Version
0.1.5
0.1.4
0.1.3
0.1.2
0.1.1
0.1.0