I am trying to use jdeps (and jlink) for deployment of my Java 11 app which is using JavaFX 11. All works fine running inside my Java IDE. But when I use jdep I get the following error, which indicates that some module or package cannot be found. I am stuck. Thanks for your help.
jdeps --list-deps --module-path /Users/…/target:/Library/Java/JavaVirtualMachines/jdk-11.0.2.jdk/Contents/Home/jmods:/Users/…/javafx-sdk-11.0.2/lib --add-modules chaincoder,javafx.fxml,javafx.base,javafx.controls,javafx.graphics,javafx.web /Users/…/target/chaincoder4-1.0.jar
Error: Module javafx.media contains package javafx.collections, module javafx.base exports package javafx.collections to javafx.media
module-info.java is
module chaincoder {
requires javafx.web;
requires javafx.graphics;
requires javafx.controls;
requires javafx.fxml;
requires javafx.base;
requires javafx.media;
requires java.desktop;
requires java.base;
requires java.xml;
requires java.logging;
requires jdk.jsobject;
exports core;
}
pom.xml is
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-graphics</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-base</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-media</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>11.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>11.0.2</version>
</dependency>
<build>
<plugins>
<plugin>
<!-- Build an executable JAR -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>core.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeScope>system</excludeScope>
<excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>11</source>
<target>11</target>
<compilerArguments>
<bootclasspath>${sun.boot.class.path}${path.separator}${java.home}/lib/jfxrt.jar</bootclasspath>
</compilerArguments>
</configuration>
</plugin>
</plugins>
</build>
Any reason why you are using the maven-dependency-plugin
plugin?
If you see what the unpack-dependencies
goal is doing, you will notice that the target/classes
folders contains more than 90 MB of classes, after the plugin extracts all the project dependencies, including the JavaFX ones, and combines them all.
And guess what happens with the different module-info.class
files for each of the different JavaFX modules? Only one prevails, in this case the one from javafx.media
.
So you have created a new module in target/classes
!
It is named javafx.media
, contains your project classes and all the JavaFX classes, and that includes all from javafx.base
or javafx.graphics
.
If you check this target/classes/module-info.class
file:
module javafx.media {
requires transitive javafx.base;
requires transitive javafx.graphics;
...
}
this "module", that already contains all the JavaFX classes, will also require again those classes from javafx.base
and javafx.graphics
, duplicating them.
This explains your error message:
Error: Module javafx.media contains package javafx.collections,
module javafx.base exports package javafx.collections to javafx.media
Now you can see that your new module javafx.media
contains many packages that are also exported from javafx.base
to it, and that violates the split package not allowed condition:
The same Java package can only be exported by a single Java module at runtime. In other words, you cannot have two (or more) modules that export the same package in use at the same time. The Java VM will complain at startup if you do.
Possible Solutions
Maybe you don't need the maven-dependency-plugin
plugin at all? Remove it if you don't need it.
You are adding the target
folder with all the JavaFX classes to the module-path:
jdeps --list-deps --module-path /Users/…/target:...
Obviously this is wrong, as the classes
folder contains all the JavaFX classes and a wrong module-info descriptor. It is not a valid module, so just remove it from the module-path.
So you can just have:
jdeps --list-deps --module-path /Users/…/javafx-sdk-11.0.2/lib
javafx.base
or javafx.graphics
, as those are included from transitive dependencies (this also applies to the dependencies listed in your pom). See for instance javafx.web. So you will have:
jdeps --list-deps --module-path /Users/…/javafx-sdk-11.0.2/lib
-add-modules chaincoder,javafx.fxml,javafx.web
But note that you have a module named chaincoder
, that already includes all the modules that are required, so you can have just this:
jdeps --list-deps --module-path /Users/…/javafx-sdk-11.0.2/lib
-add-modules chaincoder /Users/…/target/chaincoder4-1.0.jar
That should work.
On a final note, you can get rid of the jfxrt.jar
from the compiler plugin:
<configuration>
<source>11</source>
<target>11</target>
<compilerArguments>
<bootclasspath>${sun.boot.class.path}${path.separator}${java.home}/lib/jfxrt.jar</bootclasspath>
</compilerArguments>
</configuration>
As it doesn't exist anymore. You have all the JavaFX classes included in the dependencies:
<configuration>
<source>11</source>
<target>11</target>
</configuration>