Raise the minimum supported version of Gradle to 7.3

Closes gh-28100
This commit is contained in:
Andy Wilkinson
2021-09-22 09:17:45 +01:00
parent 4e884b27f8
commit 814c86c5e8
50 changed files with 277 additions and 558 deletions

View File

@@ -2,6 +2,6 @@
= Introduction
The Spring Boot Gradle Plugin provides Spring Boot support in https://gradle.org[Gradle].
It allows you to package executable jar or war archives, run Spring Boot applications, and use the dependency management provided by `spring-boot-dependencies`.
Spring Boot's Gradle plugin requires Gradle 6.8, 6.9, or 7.x and can be used with Gradle's {gradle-userguide}/configuration_cache.html[configuration cache].
Spring Boot's Gradle plugin requires Gradle 7.x (7.3 or later) and can be used with Gradle's {gradle-userguide}/configuration_cache.html[configuration cache].
In addition to this user guide, {api-documentation}[API documentation] is also available.

View File

@@ -23,29 +23,6 @@ include::../gradle/publishing/maven-publish.gradle.kts[tags=publishing]
[[publishing-your-application.maven]]
== Publishing with the Maven Plugin
WARNING: Due to its deprecation in Gradle 6, this plugin's support for publishing with Gradle's `maven` plugin is deprecated and will be removed in a future release.
Please use the `maven-publish` plugin instead.
When the {maven-plugin}[`maven` plugin] is applied, an `Upload` task for the `bootArchives` configuration named `uploadBootArchives` is automatically created.
By default, the `bootArchives` configuration contains the archive produced by the `bootJar` or `bootWar` task.
The `uploadBootArchives` task can be configured to publish the archive to a Maven repository:
[source,groovy,indent=0,subs="verbatim,attributes",role="primary"]
.Groovy
----
include::../gradle/publishing/maven.gradle[tags=upload]
----
[source,kotlin,indent=0,subs="verbatim,attributes",role="secondary"]
.Kotlin
----
include::../gradle/publishing/maven.gradle.kts[tags=upload]
----
[[publishing-your-application.distribution]]
== Distributing with the Application Plugin
When the {application-plugin}[`application` plugin] is applied a distribution named `boot` is created.

View File

@@ -63,11 +63,3 @@ When Gradle's {application-plugin}[`application` plugin] is applied to a project
5. Configures the `bootJar` task to use the `mainClassName` property as a convention for the `Start-Class` entry in its manifest.
6. Configures the `bootWar` task to use the `mainClassName` property as a convention for the `Start-Class` entry in its manifest.
[[reacting-to-other-plugins.maven]]
== Reacting to the Maven plugin
WARNING: Support for reacting to Gradle's `maven` plugin is deprecated and will be removed in a future release.
Please use the `maven-publish` plugin instead.
When Gradle's {maven-plugin}[`maven` plugin] is applied to a project, the Spring Boot plugin will configure the `uploadBootArchives` `Upload` task to ensure that no dependencies are declared in the pom that it generates.

View File

@@ -1,21 +0,0 @@
plugins {
id 'java'
id 'maven'
id 'org.springframework.boot' version '{gradle-project-version}'
}
// tag::upload[]
uploadBootArchives {
repositories {
mavenDeployer {
repository url: 'https://repo.example.com'
}
}
}
// end::upload[]
task deployerRepository {
doLast {
println uploadBootArchives.repositories.mavenDeployer.repository.url
}
}

View File

@@ -1,26 +0,0 @@
plugins {
java
maven
id("org.springframework.boot") version "{gradle-project-version}"
}
// tag::upload[]
tasks.getByName<Upload>("uploadBootArchives") {
repositories.withGroovyBuilder {
"mavenDeployer" {
"repository"("url" to "https://repo.example.com")
}
}
}
// end::upload[]
val url = tasks.getByName<Upload>("uploadBootArchives")
.repositories
.withGroovyBuilder { getProperty("mavenDeployer") }
.withGroovyBuilder { getProperty("repository") }
.withGroovyBuilder { getProperty("url") }
task("deployerRepository") {
doLast {
println(url)
}
}

View File

@@ -5,7 +5,7 @@ plugins {
// tag::main[]
bootRun {
main = 'com.example.ExampleApplication'
mainClass = 'com.example.ExampleApplication'
}
// end::main[]

View File

@@ -7,12 +7,12 @@ plugins {
// tag::main[]
tasks.getByName<BootRun>("bootRun") {
main = "com.example.ExampleApplication"
mainClass.set("com.example.ExampleApplication")
}
// end::main[]
task("configuredMainClass") {
doLast {
println(tasks.getByName<BootRun>("bootRun").main)
println(tasks.getByName<BootRun>("bootRun").mainClass.get())
}
}

View File

@@ -22,7 +22,7 @@ import org.gradle.api.Action;
import org.gradle.api.Project;
import org.gradle.api.plugins.BasePlugin;
import org.gradle.api.plugins.JavaPlugin;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.plugins.JavaPluginExtension;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskContainer;
@@ -112,7 +112,7 @@ public class SpringBootExtension {
}
private File determineMainSourceSetResourcesOutputDir() {
return this.project.getConvention().getPlugin(JavaPluginConvention.class).getSourceSets()
return this.project.getExtensions().getByType(JavaPluginExtension.class).getSourceSets()
.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput().getResourcesDir();
}

View File

@@ -32,7 +32,7 @@ import org.gradle.api.file.CopySpec;
import org.gradle.api.file.FileCollection;
import org.gradle.api.internal.IConventionAware;
import org.gradle.api.plugins.ApplicationPlugin;
import org.gradle.api.plugins.ApplicationPluginConvention;
import org.gradle.api.plugins.JavaApplication;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.jvm.application.scripts.TemplateBasedScriptGenerator;
@@ -50,11 +50,10 @@ final class ApplicationPluginAction implements PluginApplicationAction {
@Override
public void execute(Project project) {
ApplicationPluginConvention applicationConvention = project.getConvention()
.getPlugin(ApplicationPluginConvention.class);
JavaApplication javaApplication = project.getExtensions().getByType(JavaApplication.class);
DistributionContainer distributions = project.getExtensions().getByType(DistributionContainer.class);
Distribution distribution = distributions.create("boot");
configureBaseNameConvention(project, applicationConvention, distribution);
configureBaseNameConvention(project, javaApplication, distribution);
CreateStartScripts bootStartScripts = project.getTasks().create("bootStartScripts",
determineCreateStartScriptsClass());
bootStartScripts
@@ -73,9 +72,8 @@ final class ApplicationPluginAction implements PluginApplicationAction {
}
});
bootStartScripts.getConventionMapping().map("outputDir", () -> new File(project.getBuildDir(), "bootScripts"));
bootStartScripts.getConventionMapping().map("applicationName", applicationConvention::getApplicationName);
bootStartScripts.getConventionMapping().map("defaultJvmOpts",
applicationConvention::getApplicationDefaultJvmArgs);
bootStartScripts.getConventionMapping().map("applicationName", javaApplication::getApplicationName);
bootStartScripts.getConventionMapping().map("defaultJvmOpts", javaApplication::getApplicationDefaultJvmArgs);
CopySpec binCopySpec = project.copySpec().into("bin").from(bootStartScripts);
binCopySpec.setFileMode(0755);
distribution.getContents().with(binCopySpec);
@@ -90,7 +88,7 @@ final class ApplicationPluginAction implements PluginApplicationAction {
}
@SuppressWarnings("unchecked")
private void configureBaseNameConvention(Project project, ApplicationPluginConvention applicationConvention,
private void configureBaseNameConvention(Project project, JavaApplication javaApplication,
Distribution distribution) {
Method getDistributionBaseName = findMethod(distribution.getClass(), "getDistributionBaseName");
if (getDistributionBaseName != null) {
@@ -98,7 +96,7 @@ final class ApplicationPluginAction implements PluginApplicationAction {
Property<String> distributionBaseName = (Property<String>) distribution.getClass()
.getMethod("getDistributionBaseName").invoke(distribution);
distributionBaseName.getClass().getMethod("convention", Provider.class).invoke(distributionBaseName,
project.provider(() -> applicationConvention.getApplicationName() + "-boot"));
project.provider(() -> javaApplication.getApplicationName() + "-boot"));
return;
}
catch (Exception ex) {
@@ -107,7 +105,7 @@ final class ApplicationPluginAction implements PluginApplicationAction {
}
if (distribution instanceof IConventionAware) {
((IConventionAware) distribution).getConventionMapping().map("baseName",
() -> applicationConvention.getApplicationName() + "-boot");
() -> javaApplication.getApplicationName() + "-boot");
}
}

View File

@@ -36,7 +36,6 @@ import org.gradle.api.model.ObjectFactory;
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.plugins.JavaPluginExtension;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.SourceSet;
@@ -99,7 +98,7 @@ final class JavaPluginAction implements PluginApplicationAction {
}
private TaskProvider<BootJar> configureBootJarTask(Project project) {
SourceSet mainSourceSet = javaPluginConvention(project).getSourceSets()
SourceSet mainSourceSet = javaPluginExtension(project).getSourceSets()
.getByName(SourceSet.MAIN_SOURCE_SET_NAME);
Configuration developmentOnly = project.getConfigurations()
.getByName(SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME);
@@ -127,7 +126,7 @@ final class JavaPluginAction implements PluginApplicationAction {
buildImage.setGroup(BasePlugin.BUILD_GROUP);
buildImage.getArchiveFile().set(bootJar.get().getArchiveFile());
buildImage.getTargetJavaVersion()
.set(project.provider(() -> javaPluginConvention(project).getTargetCompatibility()));
.set(project.provider(() -> javaPluginExtension(project).getTargetCompatibility()));
});
}
@@ -137,7 +136,7 @@ final class JavaPluginAction implements PluginApplicationAction {
}
private void configureBootRunTask(Project project) {
FileCollection classpath = javaPluginConvention(project).getSourceSets()
FileCollection classpath = javaPluginExtension(project).getSourceSets()
.findByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath().filter(new JarTypeFileSpec());
TaskProvider<ResolveMainClassName> resolveProvider = ResolveMainClassName.registerForTask("bootRun", project,
classpath);
@@ -168,8 +167,8 @@ final class JavaPluginAction implements PluginApplicationAction {
return GradleVersion.current().getBaseVersion().compareTo(GradleVersion.version("6.7")) >= 0;
}
private JavaPluginConvention javaPluginConvention(Project project) {
return project.getConvention().getPlugin(JavaPluginConvention.class);
private JavaPluginExtension javaPluginExtension(Project project) {
return project.getExtensions().getByType(JavaPluginExtension.class);
}
private void configureUtf8Encoding(Project project) {
@@ -195,7 +194,7 @@ final class JavaPluginAction implements PluginApplicationAction {
}
private void configureAdditionalMetadataLocations(JavaCompile compile) {
SourceSetContainer sourceSets = compile.getProject().getConvention().getPlugin(JavaPluginConvention.class)
SourceSetContainer sourceSets = compile.getProject().getExtensions().getByType(JavaPluginExtension.class)
.getSourceSets();
sourceSets.stream().filter((candidate) -> candidate.getCompileJavaTaskName().equals(compile.getName()))
.map((match) -> match.getResources().getSrcDirs()).findFirst()

View File

@@ -1,60 +0,0 @@
/*
* Copyright 2012-2021 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.gradle.plugin;
import org.gradle.api.Action;
import org.gradle.api.Plugin;
import org.gradle.api.Project;
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin;
import org.gradle.api.tasks.Upload;
/**
* {@link Action} that is executed in response to the
* {@link org.gradle.api.plugins.MavenPlugin} being applied.
*
* @author Andy Wilkinson
* @deprecated since 2.5.0 in favor of using the {@link MavenPublishPlugin}
*/
@Deprecated
final class MavenPluginAction implements PluginApplicationAction {
private final String uploadTaskName;
MavenPluginAction(String uploadTaskName) {
this.uploadTaskName = uploadTaskName;
}
@Override
public Class<? extends Plugin<? extends Project>> getPluginClass() {
return org.gradle.api.plugins.MavenPlugin.class;
}
@Override
public void execute(Project project) {
project.getTasks().withType(Upload.class, (upload) -> {
if (this.uploadTaskName.equals(upload.getName())) {
project.afterEvaluate((evaluated) -> clearConfigurationMappings(upload));
}
});
}
private void clearConfigurationMappings(Upload upload) {
upload.getRepositories().withType(org.gradle.api.artifacts.maven.MavenResolver.class,
(resolver) -> resolver.getPom().getScopeMappings().getMappings().clear());
}
}

View File

@@ -33,7 +33,7 @@ import org.gradle.api.file.FileCollection;
import org.gradle.api.file.RegularFile;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.plugins.BasePlugin;
import org.gradle.api.plugins.Convention;
import org.gradle.api.plugins.ExtensionContainer;
import org.gradle.api.plugins.JavaApplication;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
@@ -43,6 +43,7 @@ import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskProvider;
import org.gradle.work.DisableCachingByDefault;
import org.springframework.boot.gradle.dsl.SpringBootExtension;
import org.springframework.boot.loader.tools.MainClassFinder;
@@ -53,6 +54,7 @@ import org.springframework.boot.loader.tools.MainClassFinder;
* @author Andy Wilkinson
* @since 2.4
*/
@DisableCachingByDefault(because = "Not worth caching")
public class ResolveMainClassName extends DefaultTask {
private static final String SPRING_BOOT_APPLICATION_CLASS_NAME = "org.springframework.boot.autoconfigure.SpringBootApplication";
@@ -145,13 +147,13 @@ public class ResolveMainClassName extends DefaultTask {
FileCollection classpath) {
TaskProvider<ResolveMainClassName> resolveMainClassNameProvider = project.getTasks()
.register(taskName + "MainClassName", ResolveMainClassName.class, (resolveMainClassName) -> {
Convention convention = project.getConvention();
ExtensionContainer extensions = project.getExtensions();
resolveMainClassName.setDescription(
"Resolves the name of the application's main class for the " + taskName + " task.");
resolveMainClassName.setGroup(BasePlugin.BUILD_GROUP);
resolveMainClassName.setClasspath(classpath);
resolveMainClassName.getConfiguredMainClassName().convention(project.provider(() -> {
String javaApplicationMainClass = getJavaApplicationMainClass(convention);
String javaApplicationMainClass = getJavaApplicationMainClass(extensions);
if (javaApplicationMainClass != null) {
return javaApplicationMainClass;
}
@@ -166,8 +168,8 @@ public class ResolveMainClassName extends DefaultTask {
}
@SuppressWarnings("deprecation")
private static String getJavaApplicationMainClass(Convention convention) {
JavaApplication javaApplication = convention.findByType(JavaApplication.class);
private static String getJavaApplicationMainClass(ExtensionContainer extensions) {
JavaApplication javaApplication = extensions.findByType(JavaApplication.class);
if (javaApplication == null) {
return null;
}

View File

@@ -117,10 +117,9 @@ public class SpringBootPlugin implements Plugin<Project> {
private void registerPluginActions(Project project, Configuration bootArchives) {
SinglePublishedArtifact singlePublishedArtifact = new SinglePublishedArtifact(bootArchives.getArtifacts());
@SuppressWarnings("deprecation")
List<PluginApplicationAction> actions = Arrays.asList(new JavaPluginAction(singlePublishedArtifact),
new WarPluginAction(singlePublishedArtifact), new MavenPluginAction(bootArchives.getUploadTaskName()),
new DependencyManagementPluginAction(), new ApplicationPluginAction(), new KotlinPluginAction());
new WarPluginAction(singlePublishedArtifact), new DependencyManagementPluginAction(),
new ApplicationPluginAction(), new KotlinPluginAction());
for (PluginApplicationAction action : actions) {
withPluginClassOfAction(action,
(pluginClass) -> project.getPlugins().withType(pluginClass, (plugin) -> action.execute(project)));

View File

@@ -71,7 +71,7 @@ class WarPluginAction implements PluginApplicationAction {
.getByName(SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME);
Configuration productionRuntimeClasspath = project.getConfigurations()
.getByName(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_CONFIGURATION_NAME);
FileCollection classpath = project.getConvention().getByType(SourceSetContainer.class)
FileCollection classpath = project.getExtensions().getByType(SourceSetContainer.class)
.getByName(SourceSet.MAIN_SOURCE_SET_NAME).getRuntimeClasspath()
.minus(providedRuntimeConfiguration(project)).minus((developmentOnly.minus(productionRuntimeClasspath)))
.filter(new JarTypeFileSpec());

View File

@@ -30,6 +30,7 @@ public class CreateBootStartScripts extends CreateStartScripts {
@Override
@Optional
@Deprecated
public String getMainClassName() {
return super.getMainClassName();
}

View File

@@ -30,6 +30,7 @@ import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.OutputDirectory;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.TaskExecutionException;
import org.gradle.work.DisableCachingByDefault;
import org.springframework.boot.loader.tools.BuildPropertiesWriter;
import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetails;
@@ -41,6 +42,7 @@ import org.springframework.boot.loader.tools.BuildPropertiesWriter.ProjectDetail
* @author Andy Wilkinson
* @since 2.0.0
*/
@DisableCachingByDefault(because = "Not worth caching")
public class BuildInfo extends ConventionTask {
private final BuildInfoProperties properties = new BuildInfoProperties(getProject());

View File

@@ -22,7 +22,6 @@ import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import groovy.lang.Closure;
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
@@ -37,7 +36,7 @@ import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.TaskAction;
import org.gradle.api.tasks.options.Option;
import org.gradle.util.ConfigureUtil;
import org.gradle.work.DisableCachingByDefault;
import org.springframework.boot.buildpack.platform.build.BuildRequest;
import org.springframework.boot.buildpack.platform.build.Builder;
@@ -63,6 +62,7 @@ import org.springframework.util.StringUtils;
* @author Julian Liebig
* @since 2.3.0
*/
@DisableCachingByDefault
public class BootBuildImage extends DefaultTask {
private static final String BUILDPACK_JVM_VERSION_KEY = "BP_JVM_VERSION";
@@ -99,11 +99,11 @@ public class BootBuildImage extends DefaultTask {
private final ListProperty<String> tags;
private final CacheSpec buildCache = new CacheSpec();
private final CacheSpec buildCache;
private final CacheSpec launchCache = new CacheSpec();
private final CacheSpec launchCache;
private final DockerSpec docker = new DockerSpec();
private final DockerSpec docker;
public BootBuildImage() {
this.archiveFile = getProject().getObjects().fileProperty();
@@ -115,6 +115,9 @@ public class BootBuildImage extends DefaultTask {
this.buildpacks = getProject().getObjects().listProperty(String.class);
this.bindings = getProject().getObjects().listProperty(String.class);
this.tags = getProject().getObjects().listProperty(String.class);
this.buildCache = getProject().getObjects().newInstance(CacheSpec.class);
this.launchCache = getProject().getObjects().newInstance(CacheSpec.class);
this.docker = getProject().getObjects().newInstance(DockerSpec.class);
}
/**
@@ -460,15 +463,6 @@ public class BootBuildImage extends DefaultTask {
action.execute(this.buildCache);
}
/**
* Customizes the {@link CacheSpec} for the build cache using the given
* {@code closure}.
* @param closure the closure
*/
public void buildCache(Closure<?> closure) {
buildCache(ConfigureUtil.configureUsing(closure));
}
/**
* Returns the launch cache that will be used when building the image.
* @return the cache
@@ -488,15 +482,6 @@ public class BootBuildImage extends DefaultTask {
action.execute(this.launchCache);
}
/**
* Customizes the {@link CacheSpec} for the launch cache using the given
* {@code closure}.
* @param closure the closure
*/
public void launchCache(Closure<?> closure) {
launchCache(ConfigureUtil.configureUsing(closure));
}
/**
* Returns the Docker configuration the builder will use.
* @return docker configuration.
@@ -516,15 +501,6 @@ public class BootBuildImage extends DefaultTask {
action.execute(this.docker);
}
/**
* Configures the Docker connection using the given {@code closure}.
* @param closure the closure to apply
* @since 2.4.0
*/
public void docker(Closure<?> closure) {
docker(ConfigureUtil.configureUsing(closure));
}
@TaskAction
void buildImage() throws DockerEngineException, IOException {
Builder builder = new Builder(this.docker.asDockerConfiguration());

View File

@@ -34,6 +34,7 @@ import org.gradle.api.specs.Spec;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.bundling.Jar;
import org.gradle.work.DisableCachingByDefault;
/**
* A custom {@link Jar} task that produces a Spring Boot executable jar.
@@ -44,6 +45,7 @@ import org.gradle.api.tasks.bundling.Jar;
* @author Phillip Webb
* @since 2.0.0
*/
@DisableCachingByDefault(because = "Not worth caching")
public class BootJar extends Jar implements BootArchive {
private static final String LAUNCHER = "org.springframework.boot.loader.JarLauncher";
@@ -64,9 +66,9 @@ public class BootJar extends Jar implements BootArchive {
private final Property<String> mainClass;
private FileCollection classpath;
private final LayeredSpec layered;
private LayeredSpec layered = new LayeredSpec();
private FileCollection classpath;
/**
* Creates a new {@code BootJar} task.
@@ -76,6 +78,7 @@ public class BootJar extends Jar implements BootArchive {
Project project = getProject();
this.bootInfSpec = project.copySpec().into("BOOT-INF");
this.mainClass = project.getObjects().property(String.class);
this.layered = project.getObjects().newInstance(LayeredSpec.class);
configureBootInfSpec(this.bootInfSpec);
getMainSpec().with(this.bootInfSpec);
project.getConfigurations().all((configuration) -> {

View File

@@ -35,6 +35,7 @@ import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
import org.gradle.api.tasks.bundling.War;
import org.gradle.work.DisableCachingByDefault;
/**
* A custom {@link War} task that produces a Spring Boot executable war.
@@ -43,6 +44,7 @@ import org.gradle.api.tasks.bundling.War;
* @author Phillip Webb
* @since 2.0.0
*/
@DisableCachingByDefault(because = "Not worth caching")
public class BootWar extends War implements BootArchive {
private static final String LAUNCHER = "org.springframework.boot.loader.WarLauncher";
@@ -59,11 +61,11 @@ public class BootWar extends War implements BootArchive {
private final Property<String> mainClass;
private FileCollection providedClasspath;
private final ResolvedDependencies resolvedDependencies = new ResolvedDependencies();
private LayeredSpec layered = new LayeredSpec();
private final LayeredSpec layered;
private FileCollection providedClasspath;
/**
* Creates a new {@code BootWar} task.
@@ -72,6 +74,7 @@ public class BootWar extends War implements BootArchive {
this.support = new BootArchiveSupport(LAUNCHER, new LibrarySpec(), new ZipCompressionResolver());
Project project = getProject();
this.mainClass = project.getObjects().property(String.class);
this.layered = project.getObjects().newInstance(LayeredSpec.class);
getWebInf().into("lib-provided", fromCallTo(this::getProvidedLibFiles));
this.support.moveModuleInfoToRoot(getRootSpec());
getRootSpec().eachFile(this.support::excludeNonZipLibraryFiles);

View File

@@ -16,11 +16,11 @@
package org.springframework.boot.gradle.tasks.bundling;
import groovy.lang.Closure;
import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.tasks.Input;
import org.gradle.util.ConfigureUtil;
import org.springframework.boot.buildpack.platform.build.Cache;
@@ -34,7 +34,9 @@ public class CacheSpec {
private Cache cache = null;
CacheSpec() {
@Inject
public CacheSpec() {
}
public Cache asCache() {
@@ -54,17 +56,6 @@ public class CacheSpec {
this.cache = Cache.volume(spec.getName());
}
/**
* Configures a volume cache using the given {@code closure}.
* @param closure the closure
*/
public void volume(Closure<?> closure) {
if (this.cache != null) {
throw new GradleException("Each image building cache can be configured only once");
}
volume(ConfigureUtil.configureUsing(closure));
}
/**
* Configuration for an image building cache stored in a Docker volume.
*/

View File

@@ -16,13 +16,11 @@
package org.springframework.boot.gradle.tasks.bundling;
import groovy.lang.Closure;
import org.gradle.api.Action;
import org.gradle.api.GradleException;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Nested;
import org.gradle.api.tasks.Optional;
import org.gradle.util.ConfigureUtil;
import org.springframework.boot.buildpack.platform.docker.configuration.DockerConfiguration;
@@ -104,15 +102,6 @@ public class DockerSpec {
action.execute(this.builderRegistry);
}
/**
* Customizes the {@link DockerRegistrySpec} that configures authentication to the
* builder registry.
* @param closure the closure to apply
*/
public void builderRegistry(Closure<?> closure) {
builderRegistry(ConfigureUtil.configureUsing(closure));
}
/**
* Returns the {@link DockerRegistrySpec} that configures authentication to the
* publishing registry.
@@ -132,15 +121,6 @@ public class DockerSpec {
action.execute(this.publishRegistry);
}
/**
* Customizes the {@link DockerRegistrySpec} that configures authentication to the
* publishing registry.
* @param closure the closure to apply
*/
public void publishRegistry(Closure<?> closure) {
publishRegistry(ConfigureUtil.configureUsing(closure));
}
/**
* Returns this configuration as a {@link DockerConfiguration} instance. This method
* should only be called when the configuration is complete and will no longer be

View File

@@ -23,11 +23,12 @@ import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import groovy.lang.Closure;
import javax.inject.Inject;
import org.gradle.api.Action;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Optional;
import org.gradle.util.ConfigureUtil;
import org.springframework.boot.loader.tools.Layer;
import org.springframework.boot.loader.tools.Layers;
@@ -54,15 +55,21 @@ public class LayeredSpec {
private boolean enabled = true;
private ApplicationSpec application = new ApplicationSpec();
private ApplicationSpec application;
private DependenciesSpec dependencies = new DependenciesSpec();
private DependenciesSpec dependencies;
@Optional
private List<String> layerOrder;
private Layers layers;
@Inject
public LayeredSpec(ObjectFactory objects) {
this.application = objects.newInstance(ApplicationSpec.class);
this.dependencies = objects.newInstance(DependenciesSpec.class);
}
/**
* Returns whether the layer tools should be included as a dependency in the layered
* archive.
@@ -128,14 +135,6 @@ public class LayeredSpec {
action.execute(this.application);
}
/**
* Customizes the {@link ApplicationSpec} using the given {@code closure}.
* @param closure the closure
*/
public void application(Closure<?> closure) {
application(ConfigureUtil.configureUsing(closure));
}
/**
* Returns the {@link DependenciesSpec} that controls the layers to which dependencies
* belong.
@@ -163,14 +162,6 @@ public class LayeredSpec {
action.execute(this.dependencies);
}
/**
* Customizes the {@link DependenciesSpec} using the given {@code closure}.
* @param closure the closure
*/
public void dependencies(Closure<?> closure) {
dependencies(ConfigureUtil.configureUsing(closure));
}
/**
* Returns the order of the layers in the archive from least to most frequently
* changing.
@@ -244,10 +235,6 @@ public class LayeredSpec {
this.intoLayers.add(this.specFactory.apply(layer));
}
public void intoLayer(String layer, Closure<?> closure) {
intoLayer(layer, ConfigureUtil.configureUsing(closure));
}
public void intoLayer(String layer, Action<IntoLayerSpec> action) {
IntoLayerSpec spec = this.specFactory.apply(layer);
action.execute(spec);
@@ -385,6 +372,11 @@ public class LayeredSpec {
*/
public static class ApplicationSpec extends IntoLayersSpec {
@Inject
public ApplicationSpec() {
super(new IntoLayerSpecFactory());
}
/**
* Creates a new {@code ApplicationSpec} with the given {@code contents}.
* @param contents specs for the layers in which application content should be
@@ -414,6 +406,11 @@ public class LayeredSpec {
*/
public static class DependenciesSpec extends IntoLayersSpec implements Serializable {
@Inject
public DependenciesSpec() {
super(new IntoLayerSpecFactory());
}
/**
* Creates a new {@code DependenciesSpec} with the given {@code contents}.
* @param contents specs for the layers in which dependencies should be included

View File

@@ -27,6 +27,7 @@ import org.gradle.api.tasks.JavaExec;
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.SourceSetOutput;
import org.gradle.jvm.toolchain.JavaLauncher;
import org.gradle.work.DisableCachingByDefault;
/**
* Custom {@link JavaExec} task for running a Spring Boot application.
@@ -34,6 +35,7 @@ import org.gradle.jvm.toolchain.JavaLauncher;
* @author Andy Wilkinson
* @since 2.0.0
*/
@DisableCachingByDefault(because = "Application should always run")
public class BootRun extends JavaExec {
private boolean optimizedLaunch = true;

View File

@@ -17,8 +17,6 @@
package org.springframework.boot.gradle.docs;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.condition.DisabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.gradle.junit.GradleMultiDslExtension;
@@ -37,14 +35,6 @@ class PublishingDocumentationTests {
GradleBuild gradleBuild;
@DisabledForJreRange(min = JRE.JAVA_16)
@TestTemplate
void mavenUpload() {
assertThat(this.gradleBuild.expectDeprecationWarningsWithAtLeastVersion("5.6")
.script("src/docs/gradle/publishing/maven").build("deployerRepository").getOutput())
.contains("https://repo.example.com");
}
@TestTemplate
void mavenPublish() {
assertThat(this.gradleBuild.script("src/docs/gradle/publishing/maven-publish").build("publishingConfiguration")

View File

@@ -68,7 +68,7 @@ public final class GradleProjectBuilder {
builder.withName(this.name);
}
if (JavaVersion.current() == JavaVersion.VERSION_17) {
NativeServices.initialize(userHome);
NativeServices.initializeOnClient(userHome);
try {
ProjectBuilderImpl.getGlobalServices();
}

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2012-2021 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.gradle.plugin;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.condition.DisabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.springframework.boot.gradle.junit.GradleCompatibility;
import org.springframework.boot.testsupport.gradle.testkit.GradleBuild;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for {@link MavenPluginAction}.
*
* @author Andy Wilkinson
*/
@DisabledForJreRange(min = JRE.JAVA_16)
@GradleCompatibility(versionsLessThan = "7.0-milestone-1")
class MavenPluginActionIntegrationTests {
GradleBuild gradleBuild;
@TestTemplate
void clearsConf2ScopeMappingsOfUploadBootArchivesTask() {
assertThat(this.gradleBuild.expectDeprecationWarningsWithAtLeastVersion("6.0.0").build("conf2ScopeMappings")
.getOutput()).contains("Conf2ScopeMappings = 0");
}
}

View File

@@ -1,74 +0,0 @@
/*
* Copyright 2012-2021 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.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.boot.gradle.tasks.bundling;
import java.io.File;
import org.gradle.testkit.runner.BuildResult;
import org.gradle.testkit.runner.TaskOutcome;
import org.junit.jupiter.api.TestTemplate;
import org.junit.jupiter.api.condition.DisabledForJreRange;
import org.junit.jupiter.api.condition.JRE;
import org.springframework.boot.gradle.junit.GradleCompatibility;
import org.springframework.boot.testsupport.gradle.testkit.GradleBuild;
import static org.assertj.core.api.Assertions.assertThat;
/**
* Integration tests for uploading Boot jars and wars using Gradle's Maven plugin.
*
* @author Andy Wilkinson
*/
@DisabledForJreRange(min = JRE.JAVA_16)
@GradleCompatibility(versionsLessThan = "7.0-milestone-1")
class MavenIntegrationTests {
GradleBuild gradleBuild;
@TestTemplate
void bootJarCanBeUploaded() {
BuildResult result = this.gradleBuild.expectDeprecationWarningsWithAtLeastVersion("6.0.0")
.build("uploadBootArchives");
assertThat(result.task(":uploadBootArchives").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(artifactWithSuffix("jar")).isFile();
assertThat(artifactWithSuffix("pom")).is(pomWith().groupId("com.example")
.artifactId(this.gradleBuild.getProjectDir().getName()).version("1.0").noPackaging().noDependencies());
}
@TestTemplate
void bootWarCanBeUploaded() {
BuildResult result = this.gradleBuild.expectDeprecationWarningsWithAtLeastVersion("6.0.0")
.build("uploadBootArchives");
assertThat(result.task(":uploadBootArchives").getOutcome()).isEqualTo(TaskOutcome.SUCCESS);
assertThat(artifactWithSuffix("war")).isFile();
assertThat(artifactWithSuffix("pom"))
.is(pomWith().groupId("com.example").artifactId(this.gradleBuild.getProjectDir().getName())
.version("1.0").packaging("war").noDependencies());
}
private File artifactWithSuffix(String suffix) {
String name = this.gradleBuild.getProjectDir().getName();
return new File(new File(this.gradleBuild.getProjectDir(), "build/repo"),
String.format("com/example/%s/1.0/%s-1.0.%s", name, name, suffix));
}
private PomCondition pomWith() {
return new PomCondition();
}
}