From a88f27168ab679a2246c4ad5981a0e3d278c022a Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Tue, 3 Feb 2015 10:48:21 +0000 Subject: [PATCH] Add support to the Gradle plugin for disabling direct use of resources The Maven plugin allows spring-boot:run to be configured so that resources are loaded from their output location rather than from src/main/resources. This commit adds an equivalent configuration option to the Gradle plugin. To disable source resources from being added to the classpath in place of those in the output location the configure the bootRun tasks like this: bootRun { addResources = false } Closes gh-2431 --- .../src/main/asciidoc/build-tool-plugins.adoc | 20 ++++-- spring-boot-integration-tests/pom.xml | 5 ++ .../boot/gradle/BootRunResourceTests.java | 69 +++++++++++++++++++ .../resources/boot-run-resources/build.gradle | 15 ++++ .../java/BootRunResourcesApplication.java | 24 +++++++ .../src/main/resources/test.txt | 0 .../boot/gradle/run/BootRunTask.java | 54 +++++++++++---- 7 files changed, 167 insertions(+), 20 deletions(-) create mode 100644 spring-boot-integration-tests/src/test/java/org/springframework/boot/gradle/BootRunResourceTests.java create mode 100644 spring-boot-integration-tests/src/test/resources/boot-run-resources/build.gradle create mode 100644 spring-boot-integration-tests/src/test/resources/boot-run-resources/src/main/java/BootRunResourcesApplication.java create mode 100644 spring-boot-integration-tests/src/test/resources/boot-run-resources/src/main/resources/test.txt diff --git a/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc b/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc index c577890f3bd..f1e606b9dbe 100644 --- a/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc +++ b/spring-boot-docs/src/main/asciidoc/build-tool-plugins.adoc @@ -376,12 +376,22 @@ To run a project in place without building a jar first you can use the "`bootRun $ gradle bootRun ---- -Running this way makes your static classpath resources (i.e. in `src/main/resources` by -default) reloadable in the live application, which can be helpful at development time. +By default, running this way makes your static classpath resources (i.e. in +`src/main/resources` by default) reloadable in the live application, which can be helpful +at development time. Making static classpath resources reloadable means that `bootRun` +does not use the output of the `processResources` task, i.e., when invoked using +`bootRun`, your application will use the resources in their unprocessed form. -NOTE: Making static classpath resources reloadable means that `bootRun` does not use the -output of the `processResources` task. When invoked using `bootRun` your application will -use the resources in their unprocessed form. +You can disable the direct use of your static classpath resources. This will mean that +the resources are no longer reloadable but the output of the `processResources` task will +be used. To do so, set `addResources` on the `bootRun` task to `false`: + +[source,groovy,indent=0,subs="verbatim,attributes"] +---- + bootRun { + addResources = false + } +---- diff --git a/spring-boot-integration-tests/pom.xml b/spring-boot-integration-tests/pom.xml index 9877154c093..dfb4615580f 100644 --- a/spring-boot-integration-tests/pom.xml +++ b/spring-boot-integration-tests/pom.xml @@ -26,6 +26,11 @@ ${gradle.version} test + + org.springframework.boot + spring-boot + test + org.springframework.boot spring-boot-dependency-tools diff --git a/spring-boot-integration-tests/src/test/java/org/springframework/boot/gradle/BootRunResourceTests.java b/spring-boot-integration-tests/src/test/java/org/springframework/boot/gradle/BootRunResourceTests.java new file mode 100644 index 00000000000..82cfb9ba271 --- /dev/null +++ b/spring-boot-integration-tests/src/test/java/org/springframework/boot/gradle/BootRunResourceTests.java @@ -0,0 +1,69 @@ +/* + * Copyright 2012-2015 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 + * + * http://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; + +import java.io.IOException; + +import org.gradle.tooling.ProjectConnection; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.springframework.boot.dependency.tools.ManagedDependencies; +import org.springframework.boot.test.OutputCapture; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertThat; + +/** + * Integration tests for bootRun's resource handling + * + * @author Andy Wilkinson + */ +public class BootRunResourceTests { + + private static final String BOOT_VERSION = ManagedDependencies.get() + .find("spring-boot").getVersion(); + + private static ProjectConnection project; + + @Rule + public OutputCapture output = new OutputCapture(); + + @BeforeClass + public static void createProject() throws IOException { + project = new ProjectCreator().createProject("boot-run-resources"); + } + + @Test + public void resourcesDirectlyFromSource() { + project.newBuild().forTasks("clean", "bootRun") + .withArguments("-PbootVersion=" + BOOT_VERSION, "-PaddResources=true") + .run(); + + assertThat(this.output.toString(), containsString("src/main/resources/test.txt")); + } + + @Test + public void resourcesFromBuildOutput() { + project.newBuild().forTasks("clean", "bootRun") + .withArguments("-PbootVersion=" + BOOT_VERSION, "-PaddResources=false") + .run(); + assertThat(this.output.toString(), + containsString("build/resources/main/test.txt")); + } + +} diff --git a/spring-boot-integration-tests/src/test/resources/boot-run-resources/build.gradle b/spring-boot-integration-tests/src/test/resources/boot-run-resources/build.gradle new file mode 100644 index 00000000000..9bc310ab9b4 --- /dev/null +++ b/spring-boot-integration-tests/src/test/resources/boot-run-resources/build.gradle @@ -0,0 +1,15 @@ +buildscript { + repositories { + mavenLocal() + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:${project.bootVersion}") + } +} + +apply plugin: 'java' +apply plugin: 'spring-boot' + +bootRun { + addResources = Boolean.valueOf(project.addResources) +} \ No newline at end of file diff --git a/spring-boot-integration-tests/src/test/resources/boot-run-resources/src/main/java/BootRunResourcesApplication.java b/spring-boot-integration-tests/src/test/resources/boot-run-resources/src/main/java/BootRunResourcesApplication.java new file mode 100644 index 00000000000..8410897f8f0 --- /dev/null +++ b/spring-boot-integration-tests/src/test/resources/boot-run-resources/src/main/java/BootRunResourcesApplication.java @@ -0,0 +1,24 @@ +/* + * Copyright 2012-2015 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 + * + * http://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. + */ + +public class BootRunResourcesApplication { + + public static void main(String[] args) { + ClassLoader classLoader = BootRunResourcesApplication.class.getClassLoader(); + System.out.println(classLoader.getResource("test.txt")); + } + +} diff --git a/spring-boot-integration-tests/src/test/resources/boot-run-resources/src/main/resources/test.txt b/spring-boot-integration-tests/src/test/resources/boot-run-resources/src/main/resources/test.txt new file mode 100644 index 00000000000..e69de29bb2d diff --git a/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/run/BootRunTask.java b/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/run/BootRunTask.java index 104a2aacf1b..76950525a3b 100644 --- a/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/run/BootRunTask.java +++ b/spring-boot-tools/spring-boot-gradle-plugin/src/main/groovy/org/springframework/boot/gradle/run/BootRunTask.java @@ -35,25 +35,49 @@ import org.springframework.boot.loader.tools.FileUtils; */ public class BootRunTask extends JavaExec { + /** + * Whether or not resources (typically in {@code src/main/resources} are added + * directly to the classpath. When enabled (the default), this allows live in-place + * editing of resources. Duplicate resources are removed from the resource output + * directory to prevent them from appearing twice if + * {@code ClassLoader.getResources()} is called. + */ + private boolean addResources = true; + + public boolean getAddResources() { + return this.addResources; + } + + public void setAddResources(boolean addResources) { + this.addResources = addResources; + } + @Override public void exec() { - SourceSet mainSourceSet = SourceSets.findMainSourceSet(getProject()); - final File outputDir = (mainSourceSet == null ? null : mainSourceSet.getOutput() - .getResourcesDir()); - final Set resources = new LinkedHashSet(); - if (mainSourceSet != null) { - resources.addAll(mainSourceSet.getResources().getSrcDirs()); - } - List classPath = new ArrayList(getClasspath().getFiles()); - classPath.addAll(0, resources); - getLogger().info("Adding classpath: " + resources); - setClasspath(new SimpleFileCollection(classPath)); - if (outputDir != null) { - for (File directory : resources) { - FileUtils.removeDuplicatesFromOutputDirectory(outputDir, directory); + addResourcesIfNecessary(); + super.exec(); + } + + private void addResourcesIfNecessary() { + System.out.println(this.addResources); + if (this.addResources) { + SourceSet mainSourceSet = SourceSets.findMainSourceSet(getProject()); + final File outputDir = (mainSourceSet == null ? null : mainSourceSet + .getOutput().getResourcesDir()); + final Set resources = new LinkedHashSet(); + if (mainSourceSet != null) { + resources.addAll(mainSourceSet.getResources().getSrcDirs()); + } + List classPath = new ArrayList(getClasspath().getFiles()); + classPath.addAll(0, resources); + getLogger().info("Adding classpath: " + resources); + setClasspath(new SimpleFileCollection(classPath)); + if (outputDir != null) { + for (File directory : resources) { + FileUtils.removeDuplicatesFromOutputDirectory(outputDir, directory); + } } } - super.exec(); } }