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 ea483ff099ac..a853e245bab9 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 BootJar() { 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 361ca73c7cce..7f7998a8b328 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 @@ void multiModuleCustomLayers() throws IOException { 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 000000000000..2f5e2250a89c --- /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() + } +}