javamavennetbeansjava-platform-module-systemjdeps

How to package an application into JPMS modules using Maven and NetBeans?


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:

enter image description here

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?


Solution

  • Finally got it. The scenario:

    You want to package your app in a way that respects the modular system. So:

    You can run this app directly with the run icon in NetBeans, or:

    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>