问题描述
问题
你如何创建一个 Java 库 jar:
- 是java模块(有
module-info
) - 有一个依赖的遗留(非模块)jar。 (比如
commons-exec
)?
依赖项是一个实现细节 - 不应导出。
来源
具有以下 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 插件设法解决了同样的问题。
此插件允许您将模块信息添加到 Java 库中 那没有。如果你这样做,你可以给它一个适当的 模块名称,Gradle 可以捡起来放到模块路径上 在编译、测试和执行期间。
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 是一个模块,并且必须放在模块路径而不是传统的类路径中。