My goal is to package an application into a modular runtime image bundled with a custom JRE, using jlink. My app is a simple "hello world" Java Standard Edition app, with a dependency to Guava. I use the JDK 11.
Basically I try to reproduce this tutorial by Baeldung, but with NetBeans, Maven to manage the dependencies and the Maven Compiler Plugin version 3.8.1 for the build with the module system.
The directory structure:
The module-info.java file:
module TestwithJLink {
requires guava;
exports net.clementlevallois.testwithjlink;
}
Controller.java:
package net.clementlevallois.testwithjlink;
import com.google.common.collect.HashMultiset;
import com.google.common.collect.Multiset;
public class Controller {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Multiset<String> test = HashMultiset.create();
test.add("hello");
test.add("world");
System.out.println("test: "+ test.toString());
}
}
The pom.xml:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.clementlevallois</groupId>
<artifactId>TestwithJLink</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<id>compile</id>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>
But it creates compiled classes, no jars or modules. So I can't go further (analyze the modules of the jar with jdeps, then using jlink). I must be missing something obvious but what?
Finally got it. The scenario:
You want to package your app in a way that respects the modular system. So:
<goal>resolve</goal>
in the maven-dependency-plugin
makes sure your dependencies are packaged with their module-info.java file, which is not the case otherwise! (see here).You can run this app directly with the run icon in NetBeans, or:
java --module-path lib --module NameOfYourModule
The POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.clementlevallois</groupId>
<artifactId>TestwithJLink</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<dependencies>
<dependency>
<groupId>net.clementlevallois</groupId>
<artifactId>utils</artifactId>
<version>1.0</version>
<type>jar</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>resolve</goal>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.2</version>
<configuration>
<archive>
<manifest>
<mainClass>net.clementlevallois.testwithjlink.Controller</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
<id>compile</id>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>