gradle 依赖项的 Noname 模块问题Java 9

问题描述

我正在尝试将现有的 JavaFX 应用程序移植到 Java 9。

这里是 build.gradle

plugins {
    id 'application'
    id 'java'
    id 'org.openjfx.javafxplugin' version '0.0.9'
}

repositories {
    mavenLocal()
    maven {
        url = uri('https://repo.maven.apache.org/maven2/')
    }
    flatDir {
        dirs 'libs'
    }
}

group = 'ru.mydomain.myapp.fx'
version = '0.7'
description = 'myAppFX'
java.sourceCompatibility = JavaVersion.VERSION_1_9

java {
    modularity.inferModulePath = true
}

sourceSets {
    main {
        java {
            srcDirs("src/common/java","src/fx/java")
        }
        resources {
            srcDirs = ['src/fx/resources']
        }
    }
}

dependencies {
    implementation 'org.slf4j:slf4j-api:1.7.25'
    implementation 'com.j256.ormlite:ormlite-jdbc:5.0'
    //blah-blah
}

javafx {
    version = "15.0.1"
    modules = [ 'javafx.controls','javafx.fxml','javafx.swing']
}
application {
    mainModule = 'mymodule.javafx'
    mainClass = 'ru.mydomain.myapp.fx.Main'
}

我的模块声明:

module mymodule.javafx {
    requires javafx.controls;
    requires javafx.fxml;
    requires javafx.swing;
    requires slf4j.api;
    requires ormlite.jdbc;

    // Export the package (needed by JavaFX to start the Application)
    // Replace "exports" with "opens" if "@FXML" is used in this module
    opens ru.mydomain.myapp.fx;

}

问题出在由 gradle 依赖项中声明的库生成的未命名模块中。在这种特殊情况下,slf4j。是的,每当我使用带有声明的 module-info.java 的新库时,它都可以解决,但是如果我使用没有 module-info.java 的旧库时,我会收到如下错误消息:

错误:找不到模块:slf4j.apI/Ormlite.jdbc/etc...

据我所知,问题出在所谓的自动/未命名模块中。

任何想法,如何使用依赖库生成的 noname 模块解决此问题?

更新

探索 com.j256.ormlite:ormlite-jdbc:5.0 依赖

  1. 清单中不包含任何 Automatic-Module-Name
  2. 确切的 jar 名称是:ormlite-jdbc-5.0.jar
  3. 双重检查 - 它在编译类路径中
  4. 确切的错误消息是:
    module-info.java:7: error: module not found: ormlite.jdbc
    requires ormlite.jdbc;
                    ^

解决方法

让我们将问题分解为最基本的问题:这是一个 Java 模块问题,它与 Gradle 或 JavaFX 几乎无关。因此,我们只需查看 Java 模块文档即可了解我们可以做什么。

我读到的是:总是有一个模块名称。如果 jar 完全不提供任何内容,则模块的名称是不带 .jar 扩展名的 jar 文件的名称。但是,还有更多内容,可以找到名称派生的确切规则here。我会引用它以防链接断开:

删除“.jar”后缀。

如果名称与正则表达式“-(\d+(\.|$))”匹配,则 模块名称将来自连字符之前的子序列 第一次出现。连字符后的子序列解析为 一个版本,如果无法解析为版本,则忽略。

模块名称中的所有非字母数字字符([^A-Za-z0-9])都是 替换为一个点(“.”),所有重复的点都替换为一个 点,并删除所有前导和尾随的点。

例如,一个名为“foo-bar.jar”的 JAR 文件将派生一个模块 名称“foo.bar”,没有版本。一个名为的 JAR 文件 “foo-bar-1.2.3-SNAPSHOT.jar”将派生一个模块名称“foo.bar”和 “1.2.3-SNAPSHOT”作为版本。

因此您需要更改 requires 语句以匹配自动命名规则。

当然,最好使用不属于古代历史的 jar 版本......

这里是关于自动模块命名的nice blog,如果还有疑问。