From 3dea2201c414a4ebe827494e2b22d507566bad63 Mon Sep 17 00:00:00 2001 From: Scott Frederick Date: Fri, 31 Jan 2020 15:54:33 -0600 Subject: [PATCH] Use Gradle's configuration avoidance API Register Boot Gradle tasks instead of creating them so they can be loaded lazily. Closes gh-18881 --- .../boot/gradle/dsl/SpringBootExtension.java | 20 +++-- .../boot/gradle/plugin/JavaPluginAction.java | 78 ++++++++++--------- .../plugin/SinglePublishedArtifact.java | 5 +- .../boot/gradle/plugin/WarPluginAction.java | 37 ++++++--- 4 files changed, 82 insertions(+), 58 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/dsl/SpringBootExtension.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/dsl/SpringBootExtension.java index 76f9f0186f3..b1ce0d4fea4 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/dsl/SpringBootExtension.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/dsl/SpringBootExtension.java @@ -24,6 +24,7 @@ import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskProvider; import org.gradle.jvm.tasks.Jar; import org.springframework.boot.gradle.tasks.buildinfo.BuildInfo; @@ -33,6 +34,7 @@ import org.springframework.boot.gradle.tasks.buildinfo.BuildInfoProperties; * Entry point to Spring Boot's Gradle DSL. * * @author Andy Wilkinson + * @author Scott Frederick * @since 2.0.0 */ public class SpringBootExtension { @@ -89,22 +91,24 @@ public class SpringBootExtension { * @param configurer the task configurer */ public void buildInfo(Action configurer) { - BuildInfo bootBuildInfo = this.project.getTasks().create("bootBuildInfo", BuildInfo.class); - bootBuildInfo.setGroup(BasePlugin.BUILD_GROUP); - bootBuildInfo.setDescription("Generates a META-INF/build-info.properties file."); + TaskProvider bootBuildInfo = this.project.getTasks().register("bootBuildInfo", BuildInfo.class, + (task) -> { + task.setGroup(BasePlugin.BUILD_GROUP); + task.setDescription("Generates a META-INF/build-info.properties file."); + task.getConventionMapping().map("destinationDir", + () -> new File(determineMainSourceSetResourcesOutputDir(), "META-INF")); + }); this.project.getPlugins().withType(JavaPlugin.class, (plugin) -> { - this.project.getTasks().getByName(JavaPlugin.CLASSES_TASK_NAME).dependsOn(bootBuildInfo); + this.project.getTasks().getByName(JavaPlugin.CLASSES_TASK_NAME).dependsOn(bootBuildInfo.get()); this.project.afterEvaluate((evaluated) -> { - BuildInfoProperties properties = bootBuildInfo.getProperties(); + BuildInfoProperties properties = bootBuildInfo.get().getProperties(); if (properties.getArtifact() == null) { properties.setArtifact(determineArtifactBaseName()); } }); - bootBuildInfo.getConventionMapping().map("destinationDir", - () -> new File(determineMainSourceSetResourcesOutputDir(), "META-INF")); }); if (configurer != null) { - configurer.execute(bootBuildInfo); + configurer.execute(bootBuildInfo.get()); } } 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 db4073f82d5..324e8af53b2 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 @@ -29,12 +29,13 @@ import org.gradle.api.Project; import org.gradle.api.Task; import org.gradle.api.artifacts.Configuration; import org.gradle.api.file.FileCollection; -import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact; +import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact; import org.gradle.api.plugins.ApplicationPlugin; import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.JavaPlugin; import org.gradle.api.plugins.JavaPluginConvention; import org.gradle.api.tasks.SourceSet; +import org.gradle.api.tasks.TaskProvider; import org.gradle.api.tasks.compile.JavaCompile; import org.springframework.boot.gradle.tasks.bundling.BootBuildImage; @@ -46,6 +47,7 @@ import org.springframework.util.StringUtils; * {@link Action} that is executed in response to the {@link JavaPlugin} being applied. * * @author Andy Wilkinson + * @author Scott Frederick */ final class JavaPluginAction implements PluginApplicationAction { @@ -66,7 +68,7 @@ final class JavaPluginAction implements PluginApplicationAction { public void execute(Project project) { disableJarTask(project); configureBuildTask(project); - BootJar bootJar = configureBootJarTask(project); + TaskProvider bootJar = configureBootJarTask(project); configureBootBuildImageTask(project, bootJar); configureArtifactPublication(bootJar); configureBootRunTask(project); @@ -76,55 +78,57 @@ final class JavaPluginAction implements PluginApplicationAction { } private void disableJarTask(Project project) { - project.getTasks().getByName(JavaPlugin.JAR_TASK_NAME).setEnabled(false); + project.getTasks().named(JavaPlugin.JAR_TASK_NAME).configure((task) -> task.setEnabled(false)); } private void configureBuildTask(Project project) { - project.getTasks().getByName(BasePlugin.ASSEMBLE_TASK_NAME).dependsOn(this.singlePublishedArtifact); + project.getTasks().named(BasePlugin.ASSEMBLE_TASK_NAME) + .configure((task) -> task.dependsOn(this.singlePublishedArtifact)); } - private BootJar configureBootJarTask(Project project) { - BootJar bootJar = project.getTasks().create(SpringBootPlugin.BOOT_JAR_TASK_NAME, BootJar.class); - bootJar.setDescription( - "Assembles an executable jar archive containing the main classes and their dependencies."); - bootJar.setGroup(BasePlugin.BUILD_GROUP); - SourceSet mainSourceSet = javaPluginConvention(project).getSourceSets() - .getByName(SourceSet.MAIN_SOURCE_SET_NAME); - bootJar.classpath((Callable) () -> mainSourceSet.getRuntimeClasspath()); - Configuration runtimeClasspathConfiguration = project.getConfigurations() - .getByName(mainSourceSet.getRuntimeClasspathConfigurationName()); - runtimeClasspathConfiguration.getIncoming().afterResolve(bootJar::resolvedDependencies); - bootJar.conventionMapping("mainClassName", new MainClassConvention(project, bootJar::getClasspath)); - return bootJar; + private TaskProvider configureBootJarTask(Project project) { + return project.getTasks().register(SpringBootPlugin.BOOT_JAR_TASK_NAME, BootJar.class, (bootJar) -> { + bootJar.setDescription( + "Assembles an executable jar archive containing the main classes and their dependencies."); + bootJar.setGroup(BasePlugin.BUILD_GROUP); + SourceSet mainSourceSet = javaPluginConvention(project).getSourceSets() + .getByName(SourceSet.MAIN_SOURCE_SET_NAME); + bootJar.classpath((Callable) mainSourceSet::getRuntimeClasspath); + Configuration runtimeClasspathConfiguration = project.getConfigurations() + .getByName(mainSourceSet.getRuntimeClasspathConfigurationName()); + runtimeClasspathConfiguration.getIncoming().afterResolve(bootJar::resolvedDependencies); + bootJar.conventionMapping("mainClassName", new MainClassConvention(project, bootJar::getClasspath)); + }); } - private void configureBootBuildImageTask(Project project, BootJar bootJar) { - BootBuildImage buildImage = project.getTasks().create(SpringBootPlugin.BOOT_BUILD_IMAGE_TASK_NAME, - BootBuildImage.class); - buildImage.setDescription("Builds an OCI image of the application using the output of the bootJar task"); - buildImage.setGroup(BasePlugin.BUILD_GROUP); - buildImage.getJar().set(bootJar.getArchiveFile()); - buildImage.getTargetJavaVersion().set(javaPluginConvention(project).getTargetCompatibility()); + private void configureBootBuildImageTask(Project project, TaskProvider bootJar) { + project.getTasks().register(SpringBootPlugin.BOOT_BUILD_IMAGE_TASK_NAME, BootBuildImage.class, (buildImage) -> { + buildImage.setDescription("Builds an OCI image of the application using the output of the bootJar task"); + buildImage.setGroup(BasePlugin.BUILD_GROUP); + buildImage.getJar().set(bootJar.get().getArchiveFile()); + buildImage.getTargetJavaVersion().set(javaPluginConvention(project).getTargetCompatibility()); + }); } - private void configureArtifactPublication(BootJar bootJar) { - ArchivePublishArtifact artifact = new ArchivePublishArtifact(bootJar); + private void configureArtifactPublication(TaskProvider bootJar) { + LazyPublishArtifact artifact = new LazyPublishArtifact(bootJar); this.singlePublishedArtifact.addCandidate(artifact); } private void configureBootRunTask(Project project) { - BootRun run = project.getTasks().create("bootRun", BootRun.class); - run.setDescription("Runs this project as a Spring Boot application."); - run.setGroup(ApplicationPlugin.APPLICATION_GROUP); - run.classpath(javaPluginConvention(project).getSourceSets().findByName(SourceSet.MAIN_SOURCE_SET_NAME) - .getRuntimeClasspath()); - run.getConventionMapping().map("jvmArgs", () -> { - if (project.hasProperty("applicationDefaultJvmArgs")) { - return project.property("applicationDefaultJvmArgs"); - } - return Collections.emptyList(); + project.getTasks().register("bootRun", BootRun.class, (run) -> { + run.setDescription("Runs this project as a Spring Boot application."); + run.setGroup(ApplicationPlugin.APPLICATION_GROUP); + run.classpath(javaPluginConvention(project).getSourceSets().findByName(SourceSet.MAIN_SOURCE_SET_NAME) + .getRuntimeClasspath()); + run.getConventionMapping().map("jvmArgs", () -> { + if (project.hasProperty("applicationDefaultJvmArgs")) { + return project.property("applicationDefaultJvmArgs"); + } + return Collections.emptyList(); + }); + run.conventionMapping("main", new MainClassConvention(project, run::getClasspath)); }); - run.conventionMapping("main", new MainClassConvention(project, run::getClasspath)); } private JavaPluginConvention javaPluginConvention(Project project) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SinglePublishedArtifact.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SinglePublishedArtifact.java index eb107ca50c6..31d13fe6e72 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SinglePublishedArtifact.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SinglePublishedArtifact.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,6 +26,7 @@ import org.gradle.api.tasks.TaskDependency; * published, with a war file taking precedence over a jar file. * * @author Andy Wilkinson + * @author Scott Frederick */ final class SinglePublishedArtifact implements Buildable { @@ -47,7 +48,7 @@ final class SinglePublishedArtifact implements Buildable { @Override public TaskDependency getBuildDependencies() { - return this.currentArtifact.getBuildDependencies(); + return this.artifacts.getBuildDependencies(); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java index b406948c8f5..0c87d234b1e 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/WarPluginAction.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2019 the original author or authors. + * Copyright 2012-2020 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,9 +20,10 @@ import org.gradle.api.Action; import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; -import org.gradle.api.internal.artifacts.publish.ArchivePublishArtifact; +import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact; import org.gradle.api.plugins.BasePlugin; import org.gradle.api.plugins.WarPlugin; +import org.gradle.api.tasks.TaskProvider; import org.springframework.boot.gradle.tasks.bundling.BootWar; @@ -30,6 +31,7 @@ import org.springframework.boot.gradle.tasks.bundling.BootWar; * {@link Action} that is executed in response to the {@link WarPlugin} being applied. * * @author Andy Wilkinson + * @author Scott Frederick */ class WarPluginAction implements PluginApplicationAction { @@ -46,19 +48,32 @@ class WarPluginAction implements PluginApplicationAction { @Override public void execute(Project project) { - project.getTasks().getByName(WarPlugin.WAR_TASK_NAME).setEnabled(false); - BootWar bootWar = project.getTasks().create(SpringBootPlugin.BOOT_WAR_TASK_NAME, BootWar.class); - bootWar.setGroup(BasePlugin.BUILD_GROUP); - bootWar.setDescription("Assembles an executable war archive containing webapp" - + " content, and the main classes and their dependencies."); - bootWar.providedClasspath(providedRuntimeConfiguration(project)); - ArchivePublishArtifact artifact = new ArchivePublishArtifact(bootWar); - this.singlePublishedArtifact.addCandidate(artifact); - bootWar.conventionMapping("mainClassName", new MainClassConvention(project, bootWar::getClasspath)); + disableWarTask(project); + TaskProvider bootWar = configureBootWarTask(project); + configureArtifactPublication(bootWar); + } + + private void disableWarTask(Project project) { + project.getTasks().named(WarPlugin.WAR_TASK_NAME).configure((war) -> war.setEnabled(false)); + } + + private TaskProvider configureBootWarTask(Project project) { + return project.getTasks().register(SpringBootPlugin.BOOT_WAR_TASK_NAME, BootWar.class, (bootWar) -> { + bootWar.setGroup(BasePlugin.BUILD_GROUP); + bootWar.setDescription("Assembles an executable war archive containing webapp" + + " content, and the main classes and their dependencies."); + bootWar.providedClasspath(providedRuntimeConfiguration(project)); + bootWar.conventionMapping("mainClassName", new MainClassConvention(project, bootWar::getClasspath)); + }); } private Configuration providedRuntimeConfiguration(Project project) { return project.getConfigurations().getByName(WarPlugin.PROVIDED_RUNTIME_CONFIGURATION_NAME); } + private void configureArtifactPublication(TaskProvider bootWar) { + LazyPublishArtifact artifact = new LazyPublishArtifact(bootWar); + this.singlePublishedArtifact.addCandidate(artifact); + } + }