【问题标题】:Error: "Package is declared 'javafx.beans.value' in module 'foo.bar'"错误:“包在模块 'foo.bar' 中声明为 'javafx.beans.value'”
【发布时间】:2019-04-14 09:11:39
【问题描述】:

我开发了一个库,module-info.java 看起来像这样:

module foo.bar {
  requires org.apache.commons.lang3;
  requires javafx.base;
  requires java.validation;
  exports foo.bar;
}

此库用于另一个项目,其中module-info.java 包含以下内容:

module other.project {
  requires org.apache.commons.lang3;
  requires javafx.base;
  requires javafx.graphics;
  requires javafx.fxml;
  requires foo.bar;
}

当我尝试使用import javafx.beans.value.WritableValue; 时出现错误

javafx.beans.valuefoo.bar 中声明,它没有 将其导出到模块other.project

更新:我创建了两个重现问题的示例项目。请找他们here下载。

我不明白为什么会这样,但我找不到解决方案。

【问题讨论】:

  • 你能发布完整的例外吗?您是否设法让每个模块独立运行,而它们之间没有依赖关系?
  • @JoséPereda 我没有得到这样的例外,这只是 IDEA 提供的信息 - 请参阅 img.picload.org/image/dcoogipr/snippet.png
  • 您是否尝试过将您的模块作为独立模块?您是否正常构建/运行它们?
  • module 'foo.bar' 独立工作,另一个我无法测试,因为 'foo.bar' 是一个严格的依赖项。
  • 是的,HelloFX 对我来说很好用。一旦我删除了其他库的依赖项,我就可以使用 JFX 库。但是如果我的项目和外部库都需要相同的外部模块,显然会有问题。

标签: java java-module java-platform-module-system java-11 javafx-11


【解决方案1】:

根据here发布的项目,您打开项目时遇到的错误是:

包'javafx.beans.property'在模块'com.example.external.lib'中声明,它不会将它导出到模块'example.project'

这个错误的原因是你正在将一些包从javafx.base 添加到你的外部库,但是这些包没有被导出到使用这个库的项目中。 javafx.beans.property 包由外部模块在内部使用,但无法导出

因此,这些是一些建议的更改,以使其发挥作用。

如果您正在创建模块化 jar(使用 module-info 类)作为另一个项目的依赖项,则不需要使用影子插件,也不需要 捆绑 jar 中的 JavaFX 依赖项。

  1. 外部库项目

所以你可以拥有相同的module-info.java 文件:

module com.example.external.lib {
    requires javafx.base;
    requires org.apache.commons.lang3;

    exports com.example.external.library;
}

build.gradle 像这样:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.google.gradle:osdetector-gradle-plugin:1.6.0'
    }
}

apply plugin: 'com.google.osdetector'
apply plugin: 'java'

ext.platform = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

dependencies {
    compile 'org.apache.commons:commons-lang3:3.8.1'
    compile "org.openjfx:javafx-base:11:$platform"
}

compileJava {
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.base'
        ]
    }
}

现在,当您运行 gradle build 时,您将生成 libs/external-library.jar,这是一个 2 KB 的 jar,没有 JavaFX 依赖项。

请注意,如果您仍想对这个外部项目做影子 jar,您可以使用 compileOnly "org.openjfx:javafx-base:11:$platform" 将 JavaFX 依赖项排除在此 jar 之外。

  1. 项目使用外部库

您可以将该 jar 添加到项目中。

build.gradle:

buildscript {
    repositories {
        jcenter()
    }

    dependencies {
        classpath 'com.google.gradle:osdetector-gradle-plugin:1.6.0'
    }
}

apply plugin: 'com.google.osdetector'
apply plugin: 'java'

ext.platform = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

dependencies {
    compile files('libs/external-library.jar')
    compile 'org.apache.commons:commons-lang3:3.8.1'
    compile "org.openjfx:javafx-base:11:$platform"
}

compileJava {
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.base'
        ]
    }
}

但是现在您的 module-info 文件应该再次包含 javafx.base 依赖项:

module example.project {
    requires javafx.base;
    requires com.example.external.lib;

    exports com.example.project;
}

你可以运行gradle build来生成一个jar,IntelliJ不会再抱怨了。

如果你想最后有个影子罐子,你也可以申请:

buildscript {
    repositories {
        mavenCentral()
        maven {
            url "https://plugins.gradle.org/m2/"
        }
    }
    dependencies {
        classpath 'com.google.gradle:osdetector-gradle-plugin:1.6.0'
    }
}

apply plugin: 'application'
apply plugin: 'com.google.osdetector'

ext.platform = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os

sourceCompatibility = JavaVersion.VERSION_11
targetCompatibility = JavaVersion.VERSION_11

repositories {
    mavenCentral()
}

dependencies {
    compile files('libs/external-library.jar')
    compile 'org.apache.commons:commons-lang3:3.8.1'
    compile "org.openjfx:javafx-base:11:$platform"
}

compileJava {
    doFirst {
        options.compilerArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.base'
        ]
    }
}

run {
    doFirst {
        jvmArgs = [
                '--module-path', classpath.asPath,
                '--add-modules', 'javafx.base'
        ]
    }
}

mainClassName = "com.example.project.PublicClass"

jar {
    manifest {
        attributes 'Main-Class': 'com.example.project.PublicClass'
    }
    from {
        configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
    }
}

这样您就可以运行java -jar build/libs/project-using-external-lib.jar。请注意,此 jar 将包含 JavaFX 类。

不推荐使用影子 jar 来分发您的项目,但由于您有自动模块 (commons-lang3),因此您不能使用 jlink,除非您将其转换为显式模块(参见 @ 987654322@).

【讨论】:

  • 感谢您的回答 - 在小型示例项目中对我有用。但是我不太确定如何根据大量尚未模块化的外部库来处理我的大型代码库。对此有什么想法吗?我对此提出了另一个问题:stackoverflow.com/questions/53314512/…
  • 我想说你可以为所有非模块化依赖项组合一个胖 jar,通过 jlink 将一个自定义 JRE 与所有模块化依赖项结合起来。 Jpackager 指日可待,它将允许为您的应用程序创建安装程序,无论它是否具有非模块化依赖项。顺便说一句,它在内部使用 jlink,所以它的工作原理和我之前描述的差不多。
  • 正如我在回答末尾提到的,还有一些“棘手”的方法可以从非模块化 jar 中生成模块。请参阅this 和此repo。这可能会帮助您将永远不会模块化的 jar 模块化。
  • 好吧,我相信我被卡住了......如果你有一个或两个依赖项,那么这种棘手的方法很好,但是对于大量的库来说,这是不可能的。如果 jpacker 可用以及何时可用,是否有任何路线图?
  • 它有一个JEP,最初的目标是Java 12,但它可能不会按时完成。无论如何,Gluon 正在开发 Java 11 的 ea 版本。
猜你喜欢
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-10
  • 1970-01-01
相关资源
最近更新 更多