多模块JavaFX maven项目打包问题



这是一个使用maven创建多模块JavaFX应用程序的尝试。

给定以下项目结构:

project
|  pom1.xml
|_____ Word Generator (Folder)
|  pom2.xml
|_____logic (folder)
|  WordGenerator
|_____UI (folder)
|  pom3.xml
|_____marty  
|  App
|  PrimaryController
|  SecondaryController
按照上述方案的顺序,我们有如下的pom文件结构:

pom1.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>org.games.marty</groupId>
<artifactId>words</artifactId>
<packaging>pom</packaging>
<version>0.1</version>
<modules>
<module>UI</module>
<module>Word Generator</module>
</modules>
<properties>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

pom2.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">
<parent>
<artifactId>words</artifactId>
<groupId>org.games.marty</groupId>
<version>0.1</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>word.generator</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>16</source>
<target>16</target>
</configuration>
</plugin>
<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>org.games.marty.logic.WordGenerator</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</pluginManagement>
</build>
</project>

pom3.xml

<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>
<artifactId>UI</artifactId>
<version>0.1</version>
<parent>
<artifactId>words</artifactId>
<groupId>org.games.marty</groupId>
<version>0.1</version>
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>16</maven.compiler.source>
<maven.compiler.target>16</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>16</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-fxml</artifactId>
<version>16</version>
</dependency>
<dependency>
<groupId>org.games.marty</groupId>
<artifactId>word.generator</artifactId>
<version>0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<release>16</release>
</configuration>
</plugin>
<plugin>
<groupId>org.openjfx</groupId>
<artifactId>javafx-maven-plugin</artifactId>
<version>0.0.6</version>
<executions>
<execution>
<!-- Default configuration for running -->
<!-- Usage: mvn clean javafx:run -->
<id>default-cli</id>
<configuration>
<mainClass>org.games.marty.App</mainClass>
</configuration>
</execution>
</executions>
</plugin>
<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>org.games.marty.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

为了让UI能够访问WordGenerator逻辑,我们试图构建应用程序的方法是将pom1.xml指令的结果maven到package

我们得到了上面提到的错误:

Error: Could not find or load main class org.games.marty.App
Caused by: java.lang.NoClassDefFoundError: javafx/application/Application

就我的理解而言,JavaFX依赖项是通过maven安装的,应该是可用的,但是它们丢失了?

使用maven-jar-plugin通过mvn package包装是不够的

mvn package,默认情况下,只是打包应用程序代码的jar,它不包括所有依赖库代码(这就是为什么当您试图运行应用程序时无法找到依赖代码)。

您可以使用程序集打包应用程序代码和依赖库,如如何使用Maven创建具有依赖关系的可执行JAR中详细介绍的那样?,尽管这种方法并不是解决你问题的唯一方法。

您需要构建某种运行时映像

构建运行时映像有很多选项,我不知道你的需求,所以我不能推荐你应该做什么。示例选项有:

  1. 一个单独目录下的应用程序和库的zip/tar文件。
  2. 创建一个包含所有依赖代码的jar。
  3. 方案1或方案2中的任意一种,加上包含打包的JRE。
  4. 包含代码和库的运行时映像,它还使用您需要的JRE和JavaFX模块的自定义运行时部分(使用jlink)。
  5. 3或4的本机安装程序(使用jpackage +本机安装程序创建工具,例如WIX, RPM, DEB安装程序创建器)。

最后一种方法(本机安装程序),是我为大多数重要应用程序推荐的打包、分发和安装方法。

你需要研究如何做到这一点

为了得到你的解决方案,你需要做你自己的研究,一旦你选择了一种方法和工具集,如果你仍然有困难,你可以创建一个关于该方法实施的新问题。

相关资源

  • 如何使用Maven创建具有依赖关系的可执行JAR ?
  • openjfx Runtime images documentation
  • maven shade插件
  • Maven Shade JavaFX运行时组件丢失
  • openjfx JavaFX maven plugin
  • <
  • jlink指南/gh><
  • jpackage脚本/gh>JEP 392:包装工具

有阴影的罐子警告

如果您使用maven shade插件将所有JavaFX代码捆绑到一个jar中,当您从Java 16+运行应用程序时,您将收到如下警告:

WARNING: Unsupported JavaFX configuration: classes were loaded from 'unnamed module @28c71909'

这表明不支持这样的配置,并且可能(也可能会)在未来和当前JavaFX平台版本中中断。因此,我不推荐包含JavaFX平台代码的阴影jar,即使这样的jar目前可能适用于您的部署。

JavaFX 11+被构建为作为一组模块使用。如果配置不是在模块路径外运行JavaFX平台,而是在类路径外运行平台代码(就像阴影jar所做的那样),则不支持配置。

最新更新