【问题标题】:JavaFX with Gradle error module not found未找到带有 Gradle 错误模块的 JavaFX
【发布时间】:2023-01-10 12:18:02
【问题描述】:

我正在 IntelliJ 中使用 JavaFX 创建一个示例演示应用程序,但我需要使用一个名为 JavaFaker 库的库。我使用 Gradle 作为构建系统,但每次我尝试添加库时,无论是作为 build.gradle 文件中的实现,还是通过 IntelliJ 项目结构选项,module.java 文件都会显示错误:找不到模块。我已经尝试将它添加到模块中,但没有任何变化。

模块信息.java

module com.example.demo1 {
    requires javafx.controls;
    requires javafx.fxml;
    requires javafaker;

    opens com.example.demo1 to javafx.fxml;
    exports com.example.demo1;
}

构建.gradle

plugins {
    id 'java'
    id 'application'
    id 'org.openjfx.javafxplugin' version '0.0.10'
    id 'org.beryx.jlink' version '2.24.1'
}

group 'com.example'
version '1.0-SNAPSHOT'

repositories {
    mavenCentral()
}

ext {
    junitVersion = '5.8.2'
    javaFakerVersion = '1.0.2'
}

sourceCompatibility = '17'
targetCompatibility = '17'

tasks.withType(JavaCompile) {
    options.encoding = 'UTF-8'
}

application {
    mainModule = 'com.example.demo1'
    mainClass = 'com.example.demo1.HelloApplication'
}

javafx {
    version = '17.0.1'
    modules = ['javafx.controls', 'javafx.fxml']
}

dependencies {
    implementation("com.github.javafaker:javafaker:${javaFakerVersion}")
    testImplementation("org.junit.jupiter:junit-jupiter-api:${junitVersion}")
    testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:${junitVersion}")
}

test {
    useJUnitPlatform()
}

jlink {
    imageZip = project.file("${buildDir}/distributions/app-${javafx.platform.classifier}.zip") as RegularFile
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'app'
    }
}

jlinkZip {
    group = 'distribution'
}

错误信息

> Task :HelloApplication.main() FAILED
Error occurred during initialization of boot layer
java.lang.module.FindException: Module javafaker not found, required by com.example.demo1

【问题讨论】:

  • 编辑,你现在可以帮忙吗?
  • 您的 Gradle 构建脚本没有定义对 javafaker 库的依赖。
  • 我删除了它,因为我的 module.info 给了我一个工具提示,上面写着“模棱两可的模块引用:javafaker”
  • 您肯定需要在依赖项中声明的 javafaker 库。放回去。
  • 再次将 javafaker 添加到 gradle 文件中。

标签: java gradle intellij-idea javafx


【解决方案1】:

我尝试了一段时间让它与 Gradle 一起工作但无法做到。我不太了解 Gradle,但除非你了解,否则我不建议尝试。

备选方案:非模块化项目

您可以通过使项目非模块化来解决此问题:

  • 删除您的module-info.java 文件。
  • 使用模块路径上的 JavaFX 模块运行您的应用程序。
    • 您已经在做的org.openjfx.javafxplugin 将通过指定要使用的模块来帮助实现这一点。
    • 要直接在 IDE 中而不是通过 Gradle 执行应用程序,您需要为 IDE 执行配置的 VM 指定模块选项(相关信息位于 openjfx.io 的入门文档中)。
  • 对于打包,切换到使用badass-runtime-plugin 而不是badass-jlink-plugin。这将通过jpackage而不是jlink打包应用程序(它不能打包非模块化应用程序或带有自动模块的应用程序)。
  • 在您的构建文件的application 块中,您不再需要为您的应用程序指定模块,因为您不再有一个。

虽然这意味着您的应用程序不再是模块化的,但在我看来,在这种情况下,这并不是什么大损失。您使用的依赖项不是定义明确的模块,因此您不能使用 jlink 为您的应用程序创建包,并且您没有完全模块化项目通常会收到的模块化封装和定义级别.

有关详细信息,请参阅入门说明,网址为:

在所选 IDE 的“Non-Modular with Gradle”部分下。

备选方案:使用 Maven

很容易让它与 Maven 一起工作。

  1. 创建一个new JavaFX project

    • 选择 Maven 而不是 Gradle 作为构建系统。
  2. 将 javafaker 依赖项添加到您的 pom.xml。

    <dependency>
        <groupId>com.github.javafaker</groupId>
        <artifactId>javafaker</artifactId>
        <version>1.0.2</version>
    </dependency>
    
  3. 按 Maven 窗口中的刷新图标,将 Maven 项目重新导入 IDE。

  4. 将 javafaker 模块的 requires 子句添加到您的 module-info.java

    requires javafaker;
    
  5. 添加代码以在您的应用程序中使用 javafaker。

    我没有使用 javafaker 的代码,所以我无法验证最后一步是否有效,但是请试一试。 . .

    我在使用 Gradle 时遇到的一些问题

    查看 Gradle Documentation 部分“使用非模块的库”:

    第三种情况是完全不提供模块信息的传统库⟩——⟩例如 commons-cli:commons-cli:1.4。Gradle 将此类库放在类路径而不是模块路径上。然后类路径被 Java 视为一个模块(所谓的未命名模块)。

    您正在使用的 javafaker 依赖项就是这种情况。它没有module-info.java,也没有在其清单文件中定义属性Automatic-Module-Name(这是本节中的其他两种情况)。其他两种情况都会导致 Gradle 将库放在模块路径上,但你的情况意味着它在类路径上。

    当您想要从您定义的命名模块访问代码时,这是一个问题,因为您创建了一个 module-info.java

    你的模块只能找到它需要的模块的代码和资源(需要在模块路径上),所以你将requires javafaker添加到module-info.java,当你尝试通过IDE运行时得到以下信息:

    java.lang.module.FindException: Module javafaker not found, required by com.example.demo1
    

    因此,按照我链接的 Gradle 文档的建议,您从 module-info.java 中删除了 requires javafaker,您在尝试编译时会得到以下信息:

    Package 'com.github.javafaker' is declared in module 'javafaker', but module 'com.example.demo1' does not read it
    

    所以你必须将库放在模块信息中才能使用它,但你不能将库放在模块信息中,因为 Gradle 放在类路径中 -> catch-22

    有一些解决方法,例如提供 VM 参数以允许访问未命名的模块(这是类路径),或者可能以某种方式修改 Gradle 构建和/或 IDE 的模块路径处理(我不知道如何),但是他们很丑。

    另一方面,对于这种情况,Maven 的行为与 Gradle 不同,它将依赖库放在模块路径上,即使它没有定义 module-info.javaAutomatic-Module-Name。这意味着它(对我而言)更容易设置和使用。

    关于模块命名的附带建议

    这不是错误,但请注意:虽然module names with numbers in them are now allowed due to a change in the module system specification,但最好不要将模块名称中的数字添加到prevent the module name and version info being confused

【讨论】:

    【解决方案2】:

    我最近遇到了类似的问题。但是,将 static 添加到 requires 语句有帮助。也许这可以解决您的问题而无需切换到 Maven。

    所以你需要添加:requires static javafaker;

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-04
      • 1970-01-01
      • 2020-08-17
      • 1970-01-01
      • 1970-01-01
      • 2020-05-05
      • 1970-01-01
      • 2020-07-28
      相关资源
      最近更新 更多