依赖于 Java 9 模块系统库中的遗留 jar 使用 gradle

Dependening on legacy jar in Java 9 Module System library using gradle

问题

你如何创建一个 java 库 jar 来同时满足:

依赖项是一个实现细节 - 不应导出。

来源

具有以下 build.gradle(使用 gradle-6.8):

plugins {
    id 'java-library'
}

group = 'test'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '15'

repositories {
    mavenCentral()
}
java {
    modularity.inferModulePath = true
}

dependencies {
    implementation 'org.apache.commons:commons-exec:1.3'
}

和以下module-info.java

module test.module {
    requires commons.exec;
}

错误

我收到以下编译错误:

module-info.java:2: error: module not found: commons.exec
    requires commons.exec;
                    ^

如果我不包含 requires commons.exec 则错误变为:

error: package org.apache.commons.exec is not visible
import org.apache.commons.exec.CommandLine;
                         ^
  (package org.apache.commons.exec is declared in the unnamed module,
   but module test.module does not read it)

commons.exec模块名称?

运行 jar --file=commons-exec-1.3.jar --describe-module 输出:

No module descriptor found. Derived automatic module.

commons.exec@1.3 automatic
requires java.base mandated
contains org.apache.commons.exec
contains org.apache.commons.exec.environment
contains org.apache.commons.exec.launcher
contains org.apache.commons.exec.util

所以 commons.exec 看起来像是 commons-exec-1.3.jar 的有效模块名称。 Intelij Idea 似乎同意并在 module-info.java 中自动完成它。虽然它在构建时失败了。

我使用 java-module-info 插件成功解决了同样的问题。

This plugin allows you to add module information to a Java library that does not have any. If you do that, you can give it a proper module name and Gradle can pick it up to put it on the module path during compilation, testing and execution.

plugins {
   id 'java-library'
   id("de.jjohannes.extra-java-module-info") version "0.6"
}

将此部分添加到您的 build.gradle 以添加 commons-exec 模块信息

  extraJavaModuleInfo {
    module("commons-exec-1.3.jar", "org.apache.commons.exec", "1.3") {
        exports("org.apache.commons.exec")
    }
}

requires org.apache.commons.exec; 添加到您的 module-info.java

编辑 1:

Gradle 7.0 完全支持 Java 模块系统。用户现在可以通过 Gradle build, test, and run Java 模块。 module-info.java 的存在会让 Gradle 推断你的 jar 是一个模块,必须放在模块路径而不是传统的类路径上。

Using libraries that are not modules