From 1bc41ec3366642cdd63330d3761621504a4c9049 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Mon, 4 May 2020 15:59:44 +0100 Subject: [PATCH] Stop developmentOnly from removing too much from executable jars and wars Fixes gh-21288 --- .../boot/gradle/plugin/JavaPluginAction.java | 18 ++++++++++++++---- .../boot/gradle/plugin/SpringBootPlugin.java | 2 ++ .../boot/gradle/plugin/WarPluginAction.java | 8 ++++++-- .../AbstractBootArchiveIntegrationTests.java | 11 ++++++++++- .../bundling/BootJarIntegrationTests.java | 2 +- .../bundling/BootWarIntegrationTests.java | 4 ++-- ...sAreNotIncludedInTheArchiveByDefault.gradle | 1 + ...sAreNotIncludedInTheArchiveByDefault.gradle | 1 + 8 files changed, 37 insertions(+), 10 deletions(-) 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 489e48fd91..ddbbec0129 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 @@ -94,8 +94,13 @@ final class JavaPluginAction implements PluginApplicationAction { bootJar.setGroup(BasePlugin.BUILD_GROUP); SourceSet mainSourceSet = javaPluginConvention(project).getSourceSets() .getByName(SourceSet.MAIN_SOURCE_SET_NAME); - bootJar.classpath((Callable) () -> mainSourceSet.getRuntimeClasspath().minus( - project.getConfigurations().getByName(SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME))); + bootJar.classpath((Callable) () -> { + Configuration developmentOnly = project.getConfigurations() + .getByName(SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME); + Configuration productionRuntimeClasspath = project.getConfigurations() + .getByName(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_NAME); + return mainSourceSet.getRuntimeClasspath().minus((developmentOnly.minus(productionRuntimeClasspath))); + }); bootJar.conventionMapping("mainClassName", new MainClassConvention(project, bootJar::getClasspath)); }); } @@ -165,8 +170,13 @@ final class JavaPluginAction implements PluginApplicationAction { .create(SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME); developmentOnly .setDescription("Configuration for development-only dependencies such as Spring Boot's DevTools."); - project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME) - .extendsFrom(developmentOnly); + Configuration runtimeClasspath = project.getConfigurations() + .getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); + Configuration productionRuntimeClasspath = project.getConfigurations() + .create(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_NAME); + productionRuntimeClasspath.setVisible(false); + productionRuntimeClasspath.setExtendsFrom(runtimeClasspath.getExtendsFrom()); + runtimeClasspath.extendsFrom(developmentOnly); } /** diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java index f9f7be1934..0de213cc66 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/plugin/SpringBootPlugin.java @@ -76,6 +76,8 @@ public class SpringBootPlugin implements Plugin { */ public static final String DEVELOPMENT_ONLY_CONFIGURATION_NAME = "developmentOnly"; + static final String PRODUCTION_RUNTIME_CLASSPATH_NAME = "productionRuntimeClasspath"; + /** * The coordinates {@code (group:name:version)} of the * {@code spring-boot-dependencies} bom. 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 c17cb1af21..4aa382c482 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 @@ -19,6 +19,7 @@ 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.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.file.FileCollection; import org.gradle.api.internal.artifacts.dsl.LazyPublishArtifact; @@ -64,8 +65,11 @@ class WarPluginAction implements PluginApplicationAction { bootWar.setDescription("Assembles an executable war archive containing webapp" + " content, and the main classes and their dependencies."); bootWar.providedClasspath(providedRuntimeConfiguration(project)); - bootWar.setClasspath(bootWar.getClasspath().minus( - project.getConfigurations().getByName(SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME))); + Configuration developmentOnly = project.getConfigurations() + .getByName(SpringBootPlugin.DEVELOPMENT_ONLY_CONFIGURATION_NAME); + Configuration productionRuntimeClasspath = project.getConfigurations() + .getByName(SpringBootPlugin.PRODUCTION_RUNTIME_CLASSPATH_NAME); + bootWar.setClasspath(bootWar.getClasspath().minus((developmentOnly.minus(productionRuntimeClasspath)))); bootWar.conventionMapping("mainClassName", new MainClassConvention(project, bootWar::getClasspath)); }); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java index 09a5d885ef..fc9b640d52 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveIntegrationTests.java @@ -46,11 +46,14 @@ abstract class AbstractBootArchiveIntegrationTests { private final String libPath; + private final String classesPath; + GradleBuild gradleBuild; - protected AbstractBootArchiveIntegrationTests(String taskName, String libPath) { + protected AbstractBootArchiveIntegrationTests(String taskName, String libPath, String classesPath) { this.taskName = taskName; this.libPath = libPath; + this.classesPath = classesPath; } @TestTemplate @@ -142,12 +145,18 @@ abstract class AbstractBootArchiveIntegrationTests { @TestTemplate void developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault() throws IOException { + File srcMainResources = new File(this.gradleBuild.getProjectDir(), "src/main/resources"); + srcMainResources.mkdirs(); + new File(srcMainResources, "resource").createNewFile(); assertThat(this.gradleBuild.build(this.taskName).task(":" + this.taskName).getOutcome()) .isEqualTo(TaskOutcome.SUCCESS); try (JarFile jarFile = new JarFile(new File(this.gradleBuild.getProjectDir(), "build/libs").listFiles()[0])) { Stream libEntryNames = jarFile.stream().filter((entry) -> !entry.isDirectory()) .map(JarEntry::getName).filter((name) -> name.startsWith(this.libPath)); assertThat(libEntryNames).containsExactly(this.libPath + "commons-io-2.6.jar"); + Stream classesEntryNames = jarFile.stream().filter((entry) -> !entry.isDirectory()) + .map(JarEntry::getName).filter((name) -> name.startsWith(this.classesPath)); + assertThat(classesEntryNames).containsExactly(this.classesPath + "resource"); } } 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 9332e649d6..982dd8bb39 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 @@ -58,7 +58,7 @@ import static org.assertj.core.api.Assertions.assertThat; class BootJarIntegrationTests extends AbstractBootArchiveIntegrationTests { BootJarIntegrationTests() { - super("bootJar", "BOOT-INF/lib/"); + super("bootJar", "BOOT-INF/lib/", "BOOT-INF/classes/"); } @TestTemplate diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests.java index 772d11e391..aa6375bfb2 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests.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. @@ -24,7 +24,7 @@ package org.springframework.boot.gradle.tasks.bundling; class BootWarIntegrationTests extends AbstractBootArchiveIntegrationTests { BootWarIntegrationTests() { - super("bootWar", "WEB-INF/lib/"); + super("bootWar", "WEB-INF/lib/", "WEB-INF/classes/"); } } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault.gradle index e4365c4ccf..003360efa5 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootJarIntegrationTests-developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault.gradle @@ -13,5 +13,6 @@ repositories { dependencies { developmentOnly("org.apache.commons:commons-lang3:3.9") + developmentOnly("commons-io:commons-io:2.6") implementation("commons-io:commons-io:2.6") } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault.gradle b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault.gradle index 5a128d2c4e..95ffda3b38 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault.gradle +++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/resources/org/springframework/boot/gradle/tasks/bundling/BootWarIntegrationTests-developmentOnlyDependenciesAreNotIncludedInTheArchiveByDefault.gradle @@ -13,5 +13,6 @@ repositories { dependencies { developmentOnly("org.apache.commons:commons-lang3:3.9") + developmentOnly("commons-io:commons-io:2.6") implementation("commons-io:commons-io:2.6") }