java - 模块 "Package is declared ' 中的错误 : 'foo.bar' javafx. beans.value'

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

我开发了一个库,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;时,我收到错误

Package javafx.beans.value is declared in foo.bar, which does not export it to module other.project.

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

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

最佳答案

基于发布的项目 here ,打开项目时出现的错误是:

Package 'javafx.beans.property' is declared in module 'com.example.external.lib', which does not export it to module 'example.project'

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

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

如果您正在创建一个模块化 jar(使用 module-info 类)作为另一个项目的依赖项,则不需要使用 Shadow 插件,也不需要捆绑您的 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 。

  • 使用外部库的项目
  • 您可以将该 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将不再提示。

    如果你想在最后有一个影子 jar ,你也可以应用:

    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,除非您将其转换为显式模块(请参阅此 answer )。

    关于java - 模块 "Package is declared ' 中的错误 : 'foo.bar' javafx. beans.value',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53248763/

    相关文章:

    java - 如何在命令行上为java在模块路径上指定多个jar文件?

    java - 列出Java9中所有必需的模块?

    java - 为什么不允许导出整个模块?

    java - JDK9中如何解决java.lang.module.ResolutionException

    java - 使用 JNA 使用 native Fortran 库时查找 SIGSEGV 原因时出现问题

    java - 安卓和数据库

    java - @Where 注释在子表上 hibernate

    java 9 未命名模块在调试时从两者读取包 [X](使用 IntelliJ)

    Java 9 上的 JavaAgent

    java - 有目的地避免 ArrayIndexOutOfBoundsException