Browse Source

Allow additional paths that trigger a reload/restart to be configured

Previously, only folders on the classpath would be watched and used
to trigger a restart/reload of the application. This commit adds a
new property spring.devtools.restart.additional-paths that can be
used to configure additional paths that should be watched for
changes. When a change occurs in one of those paths a restart or
reload will be triggered, depending on the full restart exclude
patterns configured via the existing spring.devtools.restart.exclude
property.

Closes gh-3469
pull/3667/head
Andy Wilkinson 11 years ago
parent
commit
4a25bae143
  1. 17
      spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsProperties.java
  2. 6
      spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java
  3. 21
      spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfigurationTests.java
  4. 1
      spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
  5. 18
      spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc

17
spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/DevToolsProperties.java

@ -16,6 +16,10 @@
package org.springframework.boot.devtools.autoconfigure; package org.springframework.boot.devtools.autoconfigure;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.NestedConfigurationProperty; import org.springframework.boot.context.properties.NestedConfigurationProperty;
@ -87,6 +91,11 @@ public class DevToolsProperties {
*/ */
private String triggerFile; private String triggerFile;
/**
* Additional paths to watch for changes.
*/
private List<File> additionalPaths = new ArrayList<File>();
public boolean isEnabled() { public boolean isEnabled() {
return this.enabled; return this.enabled;
} }
@ -127,6 +136,14 @@ public class DevToolsProperties {
this.triggerFile = triggerFile; this.triggerFile = triggerFile;
} }
public List<File> getAdditionalPaths() {
return this.additionalPaths;
}
public void setAdditionalPaths(List<File> additionalPaths) {
this.additionalPaths = additionalPaths;
}
} }
/** /**

6
spring-boot-devtools/src/main/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfiguration.java

@ -16,7 +16,9 @@
package org.springframework.boot.devtools.autoconfigure; package org.springframework.boot.devtools.autoconfigure;
import java.io.File;
import java.net.URL; import java.net.URL;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
@ -158,6 +160,10 @@ public class LocalDevToolsAutoConfiguration {
if (StringUtils.hasLength(triggerFile)) { if (StringUtils.hasLength(triggerFile)) {
watcher.setTriggerFilter(new TriggerFileFilter(triggerFile)); watcher.setTriggerFilter(new TriggerFileFilter(triggerFile));
} }
List<File> additionalPaths = restartProperties.getAdditionalPaths();
for (File path : additionalPaths) {
watcher.addSourceFolder(path.getAbsoluteFile());
}
return watcher; return watcher;
} }

21
spring-boot-devtools/src/test/java/org/springframework/boot/devtools/autoconfigure/LocalDevToolsAutoConfigurationTests.java

@ -16,6 +16,7 @@
package org.springframework.boot.devtools.autoconfigure; package org.springframework.boot.devtools.autoconfigure;
import java.io.File;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -45,7 +46,9 @@ import org.springframework.util.SocketUtils;
import org.thymeleaf.templateresolver.TemplateResolver; import org.thymeleaf.templateresolver.TemplateResolver;
import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.hasKey;
import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue; import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.assertThat; import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any; import static org.mockito.Matchers.any;
@ -181,6 +184,24 @@ public class LocalDevToolsAutoConfigurationTests {
assertThat(filter, instanceOf(TriggerFileFilter.class)); assertThat(filter, instanceOf(TriggerFileFilter.class));
} }
@Test
public void watchingAdditionalPaths() throws Exception {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("spring.devtools.restart.additional-paths",
"src/main/java,src/test/java");
this.context = initializeAndRun(Config.class, properties);
ClassPathFileSystemWatcher classPathWatcher = this.context
.getBean(ClassPathFileSystemWatcher.class);
Object watcher = ReflectionTestUtils.getField(classPathWatcher,
"fileSystemWatcher");
@SuppressWarnings("unchecked")
Map<File, Object> folders = (Map<File, Object>) ReflectionTestUtils.getField(
watcher, "folders");
assertThat(folders.size(), is(equalTo(2)));
assertThat(folders, hasKey(new File("src/main/java").getAbsoluteFile()));
assertThat(folders, hasKey(new File("src/test/java").getAbsoluteFile()));
}
private ConfigurableApplicationContext initializeAndRun(Class<?> config) { private ConfigurableApplicationContext initializeAndRun(Class<?> config) {
return initializeAndRun(config, Collections.<String, Object> emptyMap()); return initializeAndRun(config, Collections.<String, Object> emptyMap());
} }

1
spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc

@ -617,6 +617,7 @@ content into your application; rather pick only the properties that you need.
# ---------------------------------------- # ----------------------------------------
# DEVTOOLS ({sc-spring-boot-devtools}/autoconfigure/DevToolsProperties.{sc-ext}[DevToolsProperties]) # DEVTOOLS ({sc-spring-boot-devtools}/autoconfigure/DevToolsProperties.{sc-ext}[DevToolsProperties])
spring.devtools.restart.additional-paths= # additional paths to watch for changes
spring.devtools.restart.enabled=true # enable automatic restart spring.devtools.restart.enabled=true # enable automatic restart
spring.devtools.restart.exclude= # patterns that should be excluding for triggering a full restart spring.devtools.restart.exclude= # patterns that should be excluding for triggering a full restart
spring.devtools.restart.poll-interval= # amount of time (in milliseconds) to wait between polling for classpath changes spring.devtools.restart.poll-interval= # amount of time (in milliseconds) to wait between polling for classpath changes

18
spring-boot-docs/src/main/asciidoc/using-spring-boot.adoc

@ -894,12 +894,14 @@ commercially supported.
[[using-boot-devtools-restart-exclude]]
==== Excluding resources ==== Excluding resources
Certain resources don't necessarily need to trigger a restart when they are changed. For Certain resources don't necessarily need to trigger a restart when they are changed. For
example, Thymeleaf templates can just be edited in-place. By default changing resources example, Thymeleaf templates can just be edited in-place. By default changing resources
in `/META-INF/maven`, `/META-INF/resources` ,`/resources` ,`/static` ,`/public` or in `/META-INF/maven`, `/META-INF/resources` ,`/resources` ,`/static` ,`/public` or
`/templates` will not trigger a restart. If you want to customize these exclusions you `/templates` will not trigger a restart but will trigger a
can use the `spring.devtools.restart.exclude` property. For example, to exclude only <<using-boot-devtools-livereload, live reload>>. If you want to customize these exclusions
you can use the `spring.devtools.restart.exclude` property. For example, to exclude only
`/static` and `/public` you would set the following: `/static` and `/public` you would set the following:
[indent=0] [indent=0]
@ -909,6 +911,18 @@ can use the `spring.devtools.restart.exclude` property. For example, to exclude
[[using-boot-devtools-restart-additional-paths]]
==== Watching additional paths
You may want your application to be restarted or reloaded when you make changes to files
that are not on the classpath. To do so, use the
`spring.devtools.restart.additional-paths` property to configure additional paths to watch
for changes. You can use the `spring.devtools.restart.exclude` property
<<using-boot-devtools-restart-exclude, described above>> to control whether changes
beneath the additional paths will trigger a full restart or just a
<<using-boot-devtools-livereload, live reload>>.
[[using-boot-devtools-restart-disable]] [[using-boot-devtools-restart-disable]]
==== Disabling restart ==== Disabling restart
If you don't want to use the restart feature you can disable it using the If you don't want to use the restart feature you can disable it using the

Loading…
Cancel
Save