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
pull/24106/head
Andy Wilkinson 4 years ago
parent e2af680f02
commit 409e3ccecf

@ -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);
}
});
});
}

@ -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<String> layerNames, Map<String, List<String>> indexedLayers)
throws IOException {
Map<String, List<String>> extractedLayers = readExtractedLayers(this.gradleBuild.getProjectDir(), layerNames);

@ -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()
}
}
Loading…
Cancel
Save