Usage

Introduction

The JPacktool Maven plugin is used to create Modular Run-Time Images with JDK 9 or native installable packages via jpackage with JDK14

The JPacktool Maven Plugin extends the Agilhard-OSS jlink-jpackager-maven-plugin and is using it as a Java Library.

This in turn is based on the Apache maven-jlink-plugin.

The intended artifacts to be linked together into a Modular Run-Time Image are the jmod and jar files. JMod files can be created by using the Maven JMod Plugin and jar files can be created by using the Maven JAR Plugin.

The JPacktool Maven Plugin enhances the jlink-jpackager-maven-plugin by adding special features for projects using update4j

The JPacktool Maven plugin is intended to be part of a solution to replace the use of the Java Webstart technology which has been discontinued in newer JDK versions.

Configuration of the JPacktool Maven Plugin

To use the JPacktool Maven Plugin you have to configure it as an extensions which means the configuration in your pom file has to look like this:

<project>
  [...]
  <build>
    [...]
    <plugins>
      [...]
      <plugin>
        <groupId>net.agilhard.maven.plugins</groupId>
        <artifactId>jpacktool-maven-plugin</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <extensions>true</extensions>
        <configuration>
          <!-- configuration elements goes here -->
        </configuration>
      </plugin>
   [...]
</project>

The configuration element contains the configuration for the plugin }like any other Maven plugin. The different elements which can be configured for this plugin can identified by the goals documentation.

Requirements

Based on the foundation of the plugin it is required to have at least JDK 9 installed to use the jlink goal and at least JDK11/14 installed to use the jpackager goal. This means either you have it configured via JAVA_HOME which means to run the whole Maven build with JDK 9/11/14 or via Toolchains.

Howto configure Maven related to Toolchains can be read in the Toolchains documentation.

You need to use the special JDK-14 Early Access build that includes JPackager support to use the jpackager goal.

This JPackager JDK-14 Early Access build can be downloaded from http://jdk.java.net/14/.

Alternatively you can also use the JDK-11 backported JPackager tool wich is mentioned in Filling the Packager gap - OpenJDK mailing list - Java.net

General Usage of the JPacktool Maven Plugin

Usually you will use the Maven JPacktool Maven Plugin to create a Run Time Image or an installable Package from one or more modules within a multi module build

You will than use one submodule there with a pom.xml which uses one of the special Maven packaging types the plugin provides and a configuration for the plugin.

In other words it is not possible to create a Run Time Image or Installation Package from a single Maven Project within the same single Maven Project and you usually would not call the goals of the plugin by using a plugin execution configuration.

Let us assume you have a multi module structure which contains two modules mod-1 and mod-2 which you like to put into the resulting Run Time Image.

The parent of the multi module looks similar like this:

<project ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.corporate.maven</groupId>
    <artifactId>maven-parent</artifactId>
    <version>2.3.1</version>
  </parent>
  <groupId>com.corporate.project</groupId>
  <artifactId>parent</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>
   [...]
  <modules>
    <module>mod-1</module>
    <module>mod-2</module>
  </modules>  
   [...]
</project>

A directory structure of such a project looks like this:

.
├── mod-1
│   └── src
└── mod-2
    └── src

The mod-1 module looks similar like this:

<project ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.corporate.project</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>mod-1</artifactId>
   [...]
</project>

The mod-2 module looks similar like this:

<project ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.corporate.project</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <artifactId>mod-2</artifactId>
   [...]
</project>

If you like to create a Java Run Time Image of your modules you have to create a separate module mod-jlink which contains the configuration to create the Run Time Image which looks similar like this:

<project ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.corporate.project</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <packaging>jlink</packaging>
  <artifactId>mod-jlink</artifactId>
   [...]
</project>

The directory structure now looks like this:

.
├── mod-1
│   └── src
├── mod-2
│   └── src
└── mod-jlink
    └── src

Or if you like to create a installable package of your modules you have to create a separate module mod-jpackager which contains the configuration to create the Run Time Image which looks similar like this:

<project ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.corporate.project</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <packaging>jpackager</packaging>
  <artifactId>mod-jpackager</artifactId>
   [...]
</project>

The directory structure than looks like this:

.
├── mod-1
│   └── src
├── mod-2
│   └── src
└── mod-jpackager
    └── src

Before you can do this you have to add the configuration to the parent like shown in Configuration of the JPacktool Maven Plugin.

Now you need to define which modules should be linked into the resulting Java Run Time Image which simply can be done by defining the modules as dependencies to your mod-jlink or mod-jpackager module like this:

<project ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.corporate.project</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <packaging>jlink</packaging>
  <artifactId>mod-jlink</artifactId>
 <dependencies>
    <dependency>
      <groupId>com.corporate.project</groupId>
      <artifactId>mod-1</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>com.corporate.project</groupId>
      <artifactId>mod-2</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>  
   [...]
</project>

When you use the jpackager goal you also have to at least specify some minimal configuration with a module element specifying the main module and the main class like this:

<project ...>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>com.corporate.project</groupId>
    <artifactId>parent</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>
  <packaging>jpackager</packaging>
  <artifactId>mod-jpackager</artifactId>

  <build>
    <plugins>

      <plugin>
        <groupId>net.agilhard.maven.plugins</groupId>
        <artifactId>jpacktool-maven-plugin</artifactId>
        <extensions>true</extensions>
        <configuration>
          <verbose>true</verbose>
          <module>com.corporate.project.mod-1/MainClass</module>
        </configuration>
      </plugin>

    </plugins>

 <dependencies>
    <dependency>
      <groupId>com.corporate.project</groupId>
      <artifactId>mod-1</artifactId>
      <version>${project.version}</version>
    </dependency>
    <dependency>
      <groupId>com.corporate.project</groupId>
      <artifactId>mod-2</artifactId>
      <version>${project.version}</version>
    </dependency>
  </dependencies>  
   [...]
</project>

After you have added the appropriate configuration you can simply create the Java Run Time Image or Installable Package by calling from the root of your multi module project like this:

mvn clean package

There are some output lines similar like this:

[INFO]
[INFO] --- jlink-jpacker-plugin:1.0.0-SNAPSHOT:jlink (default-jlink) @ mod-jlink ---
[INFO] Toolchain in jpacktool-maven-plugin: jlink [ /.../jdk1.9.0_ea+181.jdk/Contents/Home/bin/jlink ]
[INFO] The following dependencies will be linked into the runtime image:
[INFO]  -> module: com.soebes.nine.one.jar ( /.../mod-1/target/mod-1-1.0-SNAPSHOT.jar )
[INFO]  -> module: com.soebes.nine.two.jar ( /.../mod-2/target/mod-2-1.0-SNAPSHOT.jar )
[INFO] Building zip: /.../mod-jlink/target/mod-jlink-1.0-SNAPSHOT.zip
[INFO]

If you like to install the resulting Java Run Time Image files into your local cache you can achieve this by using:

mvn clean install

or if you like to deploy the resulting artifacts to a remote repository you have to use:

mvn clean deploy

At the moment the resulting Java Run Time Image is packaged into a zip archive which used to transport the whole structure which is created by jlink to a repository.

The resulting Java Run Time Image directory structure looks like this:

jlink/
├── bin
├── conf
├── include
├── legal
├── lib
└── release

Packages build with the jpackager goal are deployed into the repository with a maven classifier based on the package type and the extension for the package format, eg. .rpm .msi

Maven Packaging types

The JPacktool plugin provides the following maven packaging types

Simple use cases:

  <packaging>jlink</packaging>
  <packaging>jpackager</packaging>

Use cases for projects with mixed real-modules, automatic modules and non-modular jars:

  <packaging>jpacktool-jlink</packaging>
  <packaging>jpacktool-jpackager</packaging>

Use cases for projects using update4j and want the project to use a Master Packaging pom.xml which is generating and using other pom.xml files:

  <packaging>jpacktool-generic</packaging>

Use cases for projects using update4j with explicit fine grained control in the maven build process (usually theses are just generated and used by the previous packaging type):

  <packaging>jpacktool-bootstrap</packaging>
  <packaging>jpacktool-business</packaging>

Usage for projects that are using update4j

If you want to use the JPacktool Maven Plugin in projects which use update4j you would usually do this by using the jpacktool-generic maven packaging type.

If you later find out you want more fine grained control about the build process you can have a look at what this packaging type generates as interim maven modules and check them in into your source code repository and than modify them to your needs.

update4j config files will be automatically generated by the JPacktool Maven Plugin.

This is how you specify update4j Bootstrap and Business Application for Packaging wih the plugin:

<?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.agilhard.jpacktool.demo</groupId>
  <artifactId>demo-jpacktool-gen</artifactId>
  <version>1.0.0-SNAPSHOT</version>
  <name>demo-jpacktool-gen</name>
  <description>JPacktool Generic: demo-jpacktool-gen</description>

  <packaging>jpacktool-generic</packaging>

  <build>
    <plugins>
      <plugin>
        <groupId>net.agilhard.maven.plugins</groupId>
        <artifactId>jpacktool-maven-plugin</artifactId>
        <version>1.0.0-SNAPSHOT</version>
        <extensions>true</extensions>

        <configuration>
          <verbose>true</verbose>
          <businessGroupId>net.agilhard.maven.plugins</businessGroupId>
          <businessArtifactId>demo-business</businessArtifactId>
          <businessVersion>1.0.0-SNAPSHOT</businessVersion>
          <bootstrapGroupId>net.agilhard.maven.plugins</bootstrapGroupId>
          <bootstrapArtifactId>demo-bootstrap</bootstrapArtifactId>
          <bootstrapVersion>1.0.0-SNAPSHOT</bootstrapVersion>
          <businessBaseUri>http://localhost:8080/demo/business</businessBaseUri>
          <businessBasePath>demo-business</businessBasePath>
          <bootstrapBaseUri>http://localhost:8080/demo/business</bootstrapBaseUri>
          <bootstrapBasePath>demo/bootstrap</bootstrapBasePath>
          <bootstrapMainModule>org.update4j.demo.bootstrap</bootstrapMainModule>
          <bootstrapMainClass>org.update4j.demo.bootstrap.JavaFxDelegate</bootstrapMainClass>

          <baseUri>${jpacktool.bootstrap.baseUri}</baseUri>
          <basePath>${jpacktool.bootstrap.basePath}</basePath>
        </configuration>
      </plugin>
    </plugins>
  </build>
  
</project>