I have selected Apache Commons IO, JSerialComm and Ini4J libraries via Maven repository.
But when I try to create an image via mvn javafx:jlink
I get this errors:
[INFO] --- javafx-maven-plugin:0.0.2:jlink (default-cli) @ JUSBPlotter ---
[WARNING] Required filename-based automodules detected. Please don't publish this project to a public artifact repository!
Error: automatic module cannot be used with jlink: ini4j from file:///root/.m2/repository/org/ini4j/ini4j/0.5.4/ini4j-0.5.4.jar
[ERROR] Command execution failed.
org.apache.commons.exec.ExecuteException: Process exited with an error: 1 (Exit value: 1)
at org.apache.commons.exec.DefaultExecutor.executeInternal(DefaultExecutor.java:404)
at org.apache.commons.exec.DefaultExecutor.execute(DefaultExecutor.java:166)
at org.openjfx.JavaFXBaseMojo.executeCommandLine(JavaFXBaseMojo.java:447)
I seems it have something to do with this:
Error: automatic module cannot be used with jlink:
My module file looks like this:
module org.openjfx.JUSBPlotter {
requires javafx.controls;
requires javafx.fxml;
requires com.fazecast.jSerialComm;
requires ini4j;
requires org.apache.commons.io;
opens org.openjfx.JUSBPlotter to javafx.fxml;
exports org.openjfx.JUSBPlotter;
}
And my pom.xml looks like this:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.openjfx</groupId>
<artifactId>JUSBPlotter</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>2.5.1</version>
</dependency>
<dependency>
<groupId>org.ini4j</groupId>
<artifactId>ini4j</artifactId>
<version>0.5.4</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>11</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.2</version>
<configuration>
<stripDebug>true</stripDebug>
<compress>2</compress>
<noHeaderFiles>true</noHeaderFiles>
<noManPages>true</noManPages>
<launcher>JUSBPlotter</launcher>
<jlinkImageName>JUSBPlotter</jlinkImageName>
<jlinkZipName>JUSBPlotterZip</jlinkZipName>
<mainClass>org.openjfx.JUSBPlotter.Main</mainClass>
</configuration>
</plugin>
</plugins>
</build>
</project>
So can it be that Apache Commons IO, JSerialComm and Ini4J is to old for Maven and Jlink?
How should I solve this problem? I'm using Eclipse IDE with OpenJDK 11.
The jlink
requires all dependencies to be modular. After generation, it generates a custom JRE image including the required modules. The ini4j
seems non-modular.
For non-modular dependencies, you can go with the old Classpath approach after getting the custom JRE which has been generated without non-modular ones.
Briefly, run jlink excluding the non-modulars than add the jar files of non-modulars to the generated JRE image. The modules method and Classpath method can be combined this way.
A bit of fiddling with maven plugins should do this automatically.
Example for ini4j
pom.xml
<properties>
<jlink-image-name>JUSBPlotter</jlink-image-name>
<ini4j-jar-name>ini4j.jar</ini4j-jar-name>
</properties>
ini4j
from module-info.java
(It should be enable during development, only do this when you want to package the project)module org.openjfx.JUSBPlotter {
requires javafx.controls;
requires javafx.fxml;
requires com.fazecast.jSerialComm;
//requires ini4j;
requires org.apache.commons.io;
opens org.openjfx.JUSBPlotter to javafx.fxml;
exports org.openjfx.JUSBPlotter;
}
maven-dependency-plugin
to copy the jar file of ini4j
into the lib/
folder in jlink image.<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<!-- Copy ini4j jar into the jlink image -->
<artifactItem>
<groupId>org.ini4j</groupId>
<artifactId>ini4j</artifactId>
<version>0.5.4</version>
<type>jar</type>
<destFileName>${ini4j-jar-name}</destFileName>
</artifactItem>
</artifactItems>
<!-- Set output directory to lib folder in jlink image -->
<outputDirectory>${project.build.directory}/${jlink-image-name}/lib</outputDirectory>
<overWriteReleases>true</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</plugin>
jlink
launcher option in the javafx-maven-plugin
in order to add the jar file of non-modular ini4j
to the Classpath.<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.8</version>
<configuration>
<stripDebug>true</stripDebug>
<compress>2</compress>
<noHeaderFiles>true</noHeaderFiles>
<noManPages>true</noManPages>
<launcher>JUSBPlotter</launcher>
<jlinkImageName>JUSBPlotter</jlinkImageName>
<mainClass>org.openjfx.JUSBPlotter.Main</mainClass>
<!-- ini4j jar file will be copied to the {image-folder}/lib/ folder. The launcher script should have this option to add it to the classpath -->
<options>-cp ../lib/${init4j-jar-name}</options>
</configuration>
</plugin>
Run:
mvn clean javafx:jlink
mvn package
cd target/JUSBPlotter/bin
./JUSBPlotter
maven-dependeny-plugin
will copy the jar file when you run mvn package
. But the jlink image must be already generated. So run the mvn javafx:jlink
first. Then run mvn package
.
Refer here to see how I applied for sqlite-jdbc
in my project.