Spring 启动 Gradle 多项目构建在测试期间看不到内部依赖项
Spring Boot Gradle multi-project build not seeing internal dependencies during tests
我在从 Gradle 4 迁移到 5 的大型多项目构建中遇到问题,并在更小、更简洁的构建中复制了该问题以演示该问题。
我在构建中有 2 个项目。一个是另一个使用的依赖(基础库)。
demo (root project)
|- build.gradle
|
|--- demo-web
|---|- build.gradle
|
|--- demo-dependency
|---|- build.gradle
演示网页片段:build.gradle
...
dependencies {
implementation project(':demo-dependency')
...
}
...
依赖项目定义了一个class用于web项目,DownstreamThing
。
Web 项目试图使用它来构建自己的对象,但在根项目级别的构建过程中失败了。
> ./gradlew build
> Task :demo-web:test
com.example.demo.ThingTest > testThing FAILED
java.lang.NoClassDefFoundError at ThingTest.java:12
Caused by: java.lang.ClassNotFoundException at ThingTest.java:12
ThingTest.java
@Test
public void testThing() {
DownstreamThing t = new DownstreamThing(); //line 12, ClassNotFoundException
assertTrue(t != null);
}
我在 Gradle 4 中没有遇到任何问题,但仅在 Gradle 5. 为什么在测试任务期间找不到依赖项?
示例的完整来源在这里:https://bitbucket.org/travelsized/gradle-problem/src/master/
我相信你得到那个异常的原因是因为你已经将 Spring 引导插件应用到 demo-dependency
项目。这个插件所做的是将jar文件重新打包成一个fat jar,需要一个特殊的类加载器来加载内容。
您仍然可以在没有插件的依赖项项目中使用 Spring 引导依赖项(例如 starters)。所以,如果可以,请将其删除。
如果有特殊原因,您需要保留原始 jar 文件,以便将其用作实际依赖项。对于 Spring Boot 1.5.x,你可以这样来做:
bootRepackage {
classifier = "boot"
}
bootJar {
enabled = true
}
但请注意,我不认为 Spring Boot 1.5 与 Gradle 5 及更高版本完全兼容(目前我们使用的是 6.0),因此您可能需要降级Gradle 或升级 Spring Boot.
Bjørn Vester 的回答让我找到了正确的方向。 spring-boot 插件导致 jar 任务出错。我需要确保在启用 jar 任务时禁用依赖项的 bootJar 任务。
Gradle 和 Spring 引导插件版本之间的配置更改使它在升级中丢失。
以前,我可以为 jar post-boot:
指定一个分类器
bootRepackage {
classifier = 'exec'
}
现在,我需要启用和禁用相应的任务:
bootJar {
enabled = false
}
jar {
enabled = true
archiveBaseName = "demo-dependency"
}
在较大的项目中,我之前有一个 jar
任务指定了 archiveBaseName
,但没有 明确地 启用它来覆盖 bootJar
任务。一旦我进行了上述更改(同时保持引导插件就位),一切就开始起作用了。
我在从 Gradle 4 迁移到 5 的大型多项目构建中遇到问题,并在更小、更简洁的构建中复制了该问题以演示该问题。
我在构建中有 2 个项目。一个是另一个使用的依赖(基础库)。
demo (root project)
|- build.gradle
|
|--- demo-web
|---|- build.gradle
|
|--- demo-dependency
|---|- build.gradle
演示网页片段:build.gradle
...
dependencies {
implementation project(':demo-dependency')
...
}
...
依赖项目定义了一个class用于web项目,DownstreamThing
。
Web 项目试图使用它来构建自己的对象,但在根项目级别的构建过程中失败了。
> ./gradlew build
> Task :demo-web:test
com.example.demo.ThingTest > testThing FAILED
java.lang.NoClassDefFoundError at ThingTest.java:12
Caused by: java.lang.ClassNotFoundException at ThingTest.java:12
ThingTest.java
@Test
public void testThing() {
DownstreamThing t = new DownstreamThing(); //line 12, ClassNotFoundException
assertTrue(t != null);
}
我在 Gradle 4 中没有遇到任何问题,但仅在 Gradle 5. 为什么在测试任务期间找不到依赖项?
示例的完整来源在这里:https://bitbucket.org/travelsized/gradle-problem/src/master/
我相信你得到那个异常的原因是因为你已经将 Spring 引导插件应用到 demo-dependency
项目。这个插件所做的是将jar文件重新打包成一个fat jar,需要一个特殊的类加载器来加载内容。
您仍然可以在没有插件的依赖项项目中使用 Spring 引导依赖项(例如 starters)。所以,如果可以,请将其删除。
如果有特殊原因,您需要保留原始 jar 文件,以便将其用作实际依赖项。对于 Spring Boot 1.5.x,你可以这样来做:
bootRepackage {
classifier = "boot"
}
bootJar {
enabled = true
}
但请注意,我不认为 Spring Boot 1.5 与 Gradle 5 及更高版本完全兼容(目前我们使用的是 6.0),因此您可能需要降级Gradle 或升级 Spring Boot.
Bjørn Vester 的回答让我找到了正确的方向。 spring-boot 插件导致 jar 任务出错。我需要确保在启用 jar 任务时禁用依赖项的 bootJar 任务。
Gradle 和 Spring 引导插件版本之间的配置更改使它在升级中丢失。
以前,我可以为 jar post-boot:
指定一个分类器bootRepackage {
classifier = 'exec'
}
现在,我需要启用和禁用相应的任务:
bootJar {
enabled = false
}
jar {
enabled = true
archiveBaseName = "demo-dependency"
}
在较大的项目中,我之前有一个 jar
任务指定了 archiveBaseName
,但没有 明确地 启用它来覆盖 bootJar
任务。一旦我进行了上述更改(同时保持引导插件就位),一切就开始起作用了。