Skip to content
HGuillemet edited this page Mar 9, 2022 · 4 revisions

JavaCPP presets and JavaFX use similar methods to bundle native libraries in jar files.

Both have one native maven artifacts for each platform and one or two java maven artifacts common to all platforms.

Both also use a maven property, javafx.platform or javacpp.platform, to control the platform-specific dependencies.

However they differ in what each artifact contains. Here are two examples: javafx-graphics and opencv:

Common artifact Platform artifact
Name javafx-graphics-17.0.2.jar javafx-graphics-17.0.2-linux.jar
Content Nothing Java classes and native libraries
JPMS module javafx.graphicsEmpty (automatic module) javafx.graphics
Common artifact 1 Common artifact 2 Platform artifact
Name opencv-platform-4.5.3-1.5.6.jar opencv-4.5.3-1.5.6.jar opencv-4.5.3-1.5.6-linux-x86_64-gpu.jar
Content Nothing Java classes Native libraries
JPMS module org.bytedeco.opencv.platform org.bytedeco.opencv org.bytedeco.opencv.linux.x86_64.gpu

They also differ in that javafx.platform defaults to the host platform, while javacpp.platform defaults to all available platforms.

Let's consider a modular application using both JavaFX and OpenCV. Running such application is not a problem. We can either use the run goal of the JavaFX Maven plugin, the java goal of the Exec Maven plugin, or manually launch java with a module path computed from Maven dependencies and option --add-modules ALL-MODULE-PATH.

Building a JLink image is a bit more tricky.

One option is to follow the JavaCPP way, as explained here: use Apache Maven JLink plugin that by default builds jlink module path (--module-path option) AND the jlink module graph (--add-modules option) using all Maven dependencies. However, since the maven dependencies of our application include the JavaFX common artifact which is an automatic module, JLink fails. This could be solved if the Apache JLink Maven filtered out the automatic module but that's not currently the case (see this issue). or if JavaFX common artifacts were true named modules.

Another option is to use the JavaFX Maven plugin and its jlink goal. Unlike the Apache plugin, this plugin only adds the application module as the root of the module graph, and relies on module descriptors to bring other required modules in the graph. This work well for JavaFX, since the automatic module, which is not required, will be skipped and not included in the image. But not for JavaCPP, since the platform artifacts won't be included in the image. There is currently no way with this plugin to generate other --add-modules argument for jlink. Some attempts have been made to add the necessary features to JavaFX Maven Plugin (see this PR), but they have not been finalized.

At the end of the day, there is no good solution for building a JLink image with both JavaCPP and JavaFX maven artifacts. We suggest instead to download a JDK including JavaFX from Gluon or Azul, remove the JavaFX maven dependencies from your POM, and use the Apache JLink Maven plugin.