From ba2336844080dd6b279691e2b8e18696f3ed68c1 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 26 May 2020 12:51:33 +0100 Subject: [PATCH] Configure attributes on productionRuntimeClasspath Previously, the productionRuntimeClasspath configuration was created without any attributes. This caused problems with multi-project dependency resolution as there was insufficient information for Gradle to determine which variant of a dependency should be used by the productionRuntimeClasspath configuration. This commit updates the configuration to have three attributes, each configured with the same values as those of Gradle's own runtimeClasspathConfiguration. Fixes gh-21549 --- .../boot/gradle/plugin/JavaPluginAction.java | 11 +++++++++++ .../plugin/JavaPluginActionIntegrationTests.java | 9 +++++++++ .../plugin/JavaPluginActionIntegrationTests.gradle | 10 ++++++++++ 3 files changed, 30 insertions(+) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java index ddbbec0129..164f6a02ee 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/JavaPluginAction.java @@ -28,8 +28,13 @@ import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; +import org.gradle.api.attributes.AttributeContainer; +import org.gradle.api.attributes.Bundling; +import org.gradle.api.attributes.LibraryElements; +import org.gradle.api.attributes.Usage; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact; +import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.ApplicationPlugin; import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.JavaPlugin; @@ -174,6 +179,12 @@ final class JavaPluginAction implements PluginApplicationAction { .getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); Configuration productionRuntimeClasspath = project.getConfigurations() .create(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_NAME); + AttributeContainer attributes = productionRuntimeClasspath.getAttributes(); + ObjectFactory objectFactory = project.getObjects(); + attributes.attribute(Usage.USAGE_ATTRIBUTE, objectFactory.named(Usage.class, Usage.JAVA_RUNTIME)); + attributes.attribute(Bundling.BUNDLING_ATTRIBUTE, objectFactory.named(Bundling.class, Bundling.EXTERNAL)); + attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, + objectFactory.named(LibraryElements.class, LibraryElements.JAR)); productionRuntimeClasspath.setVisible(false); productionRuntimeClasspath.setExtendsFrom(runtimeClasspath.getExtendsFrom()); runtimeClasspath.extendsFrom(developmentOnly); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java index 8cee10dab3..c2625ba535 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.java @@ -146,6 +146,15 @@ class JavaPluginActionIntegrationTests { .contains("developmentOnly exists = true"); } + @TestTemplate + void productionRuntimeClasspathIsConfiguredWithAttributes() { + assertThat(this.gradleBuild + .build("configurationAttributes", "-PconfigurationName=productionRuntimeClasspath", "-PapplyJavaPlugin") + .getOutput()).contains("3 productionRuntimeClasspath attributes:") + .contains("org.gradle.usage: java-runtime").contains("org.gradle.libraryelements: jar") + .contains("org.gradle.dependency.bundling: external"); + } + private void createMinimalMainSource() throws IOException { File examplePackage = new File(this.gradleBuild.getProjectDir(), "src/main/java/com/example"); examplePackage.mkdirs(); diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.gradle index 8854ae1ba4..4446a07a06 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/plugin/JavaPluginActionIntegrationTests.gradle @@ -25,3 +25,13 @@ task('configurationExists') { println "${configurationName} exists = ${configurations.findByName(configurationName) != null}" } } + +task('configurationAttributes') { + doFirst { + def attributes = configurations.findByName(configurationName).attributes + println "${attributes.keySet().size()} ${configurationName} attributes:" + attributes.keySet().each { attribute -> + println " ${attribute}: ${attributes.getAttribute(attribute)}" + } + } +} \ No newline at end of file