From 409e3ccecfbf37de0ba8fe06f655c8d3fe6b9941 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 9 Nov 2020 10:10:10 +0000 Subject: [PATCH] Ignore resolution of copied configuration When a Configuration is copied, any before and after resolve actions that are registered with its ResolvableDependencies are also copied over. This means that, when a copied configuration is resolved the resolution actions may be called on a ResolvableDependencies instances that isn't the one to which they were added. Previously, the above-described Gradle behaviour would result in BootJar accessed the ResolvedConfiguration of a Configuration that may not have yet been resolved. At best this would trigger Configuration resolution and at worst it would fail. A failure could occur if the configuration had been copied so that it could be made resolvable. The afterResolve action would then try to access the ResolvedConfiguration of the original Configuration. This would trigger a resolution attempt that fails due to the original configuration being marked as unresolvable. This commit updates the afterResolve action in BootJar to check that the ResolvableDependencies with which it is called matches the ResolvableDependencies with which it was original registered. Only when the two match, and therefore the configuration has actually been resolved, does processing proceed. Fixes gh-24072 --- .../boot/gradle/tasks/bundling/BootJar.java | 7 +++++-- .../tasks/bundling/BootJarIntegrationTests.java | 7 +++++++ ...rationIsResolvedThenResolutionSucceeds.gradle | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-whenAResolvableCopyOfAnUnresolvableConfigurationIsResolvedThenResolutionSucceeds.gradle diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java index ea483ff099a..a853e245bab 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java @@ -80,8 +80,11 @@ public class BootJar extends Jar implements BootArchive { getMainSpec().with(this.bootInfSpec); getProject().getConfigurations().all((configuration) -> { ResolvableDependencies incoming = configuration.getIncoming(); - incoming.afterResolve( - (resolvableDependencies) -> this.resolvedDependencies.processConfiguration(configuration)); + incoming.afterResolve((resolvableDependencies) -> { + if (resolvableDependencies == incoming) { + this.resolvedDependencies.processConfiguration(configuration); + } + }); }); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java index 361ca73c7cc..7f7998a8b32 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests.java @@ -289,6 +289,13 @@ class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests { assertExtractedLayers(layerNames, indexedLayers); } + @TestTemplate + void whenAResolvableCopyOfAnUnresolvableConfigurationIsResolvedThenResolutionSucceeds() { + BuildResult build = this.gradleBuild.build("resolveResolvableCopyOfUnresolvableConfiguration"); + assertThat(build.task(":resolveResolvableCopyOfUnresolvableConfiguration").getOutcome()) + .isEqualTo(TaskOutcome.SUCCESS); + } + private void assertExtractedLayers(List layerNames, Map> indexedLayers) throws IOException { Map> extractedLayers = readExtractedLayers(this.gradleBuild.getProjectDir(), layerNames); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-whenAResolvableCopyOfAnUnresolvableConfigurationIsResolvedThenResolutionSucceeds.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-whenAResolvableCopyOfAnUnresolvableConfigurationIsResolvedThenResolutionSucceeds.gradle new file mode 100644 index 00000000000..2f5e2250a89 --- /dev/null +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-whenAResolvableCopyOfAnUnresolvableConfigurationIsResolvedThenResolutionSucceeds.gradle @@ -0,0 +1,16 @@ +plugins { + id 'java' + id 'org.springframework.boot' version '{version}' +} + +bootJar { + mainClass = 'com.example.Application' +} + +task resolveResolvableCopyOfUnresolvableConfiguration { + doFirst { + def copy = configurations.implementation.copyRecursive() + copy.canBeResolved = true + copy.resolve() + } +}