Applications that use spring-boot-devtools automatically restart whenever files on the classpath change. This can be a useful feature when working in an IDE, as it gives a very fast feedback loop for code changes. By default, any entry on the classpath that points to a directory is monitored for changes. Note that certain resources, such as static assets and view templates, do not need to restart the application.

If you are restarting with Maven or Gradle using the build plugin you must leave the forking set to enabled. If you disable forking, the isolated application classloader used by devtools will not be created and restarts will not operate properly.
Automatic restart works very well when used with LiveReload. See the LiveReload section for details. If you use JRebel, automatic restarts are disabled in favor of dynamic class reloading. Other devtools features (such as LiveReload and property overrides) can still be used.
DevTools relies on the application context’s shutdown hook to close it during a restart. It does not work correctly if you have disabled the shutdown hook (SpringApplication.setRegisterShutdownHook(false)).
Automatic restart is not supported when using AspectJ weaving.

Logging Changes in Condition Evaluation

By default, each time your application restarts, a report showing the condition evaluation delta is logged. The report shows the changes to your application’s auto-configuration as you make changes such as adding or removing beans and setting configuration properties.

To disable the logging of the report, set the following property:

  • Properties

  • YAML

spring.devtools.restart.log-condition-evaluation-delta=false
spring:
  devtools:
    restart:
      log-condition-evaluation-delta: false

Excluding Resources

Certain resources do not necessarily need to trigger a restart when they are changed. For example, Thymeleaf templates can be edited in-place. By default, changing resources in /META-INF/maven, /META-INF/resources, /resources, /static, /public, or /templates does not trigger a restart but does trigger a 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 property:

  • Properties

  • YAML

spring.devtools.restart.exclude=static/**,public/**
spring:
  devtools:
    restart:
      exclude: "static/**,public/**"
If you want to keep those defaults and add additional exclusions, use the spring.devtools.restart.additional-exclude property instead.

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 described earlier to control whether changes beneath the additional paths trigger a full restart or a live reload.

Disabling Restart

If you do not want to use the restart feature, you can disable it by using the spring.devtools.restart.enabled property. In most cases, you can set this property in your application.properties (doing so still initializes the restart classloader, but it does not watch for file changes).

If you need to completely disable restart support (for example, because it does not work with a specific library), you need to set the spring.devtools.restart.enabled System property to false before calling SpringApplication.run(…​), as shown in the following example:

  • Java

  • Kotlin

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class MyApplication {

	public static void main(String[] args) {
		System.setProperty("spring.devtools.restart.enabled", "false");
		SpringApplication.run(MyApplication.class, args);
	}

}
import org.springframework.boot.autoconfigure.SpringBootApplication
import org.springframework.boot.runApplication

@SpringBootApplication
class MyApplication

fun main(args: Array<String>) {
	System.setProperty("spring.devtools.restart.enabled", "false")
	runApplication<MyApplication>(*args)
}

Using a Trigger File

If you work with an IDE that continuously compiles changed files, you might prefer to trigger restarts only at specific times. To do so, you can use a “trigger file”, which is a special file that must be modified when you want to actually trigger a restart check.

Any update to the file will trigger a check, but restart only actually occurs if Devtools has detected it has something to do.

To use a trigger file, set the spring.devtools.restart.trigger-file property to the name (excluding any path) of your trigger file. The trigger file must appear somewhere on your classpath.

For example, if you have a project with the following structure:

src
+- main
   +- resources
      +- .reloadtrigger

Then your trigger-file property would be:

  • Properties

  • YAML

spring.devtools.restart.trigger-file=.reloadtrigger
spring:
  devtools:
    restart:
      trigger-file: ".reloadtrigger"

Restarts will now only happen when the src/main/resources/.reloadtrigger is updated.

You might want to set spring.devtools.restart.trigger-file as a global setting, so that all your projects behave in the same way.

Some IDEs have features that save you from needing to update your trigger file manually. Spring Tools for Eclipse and IntelliJ IDEA (Ultimate Edition) both have such support. With Spring Tools, you can use the “reload” button from the console view (as long as your trigger-file is named .reloadtrigger). For IntelliJ IDEA, you can follow the instructions in their documentation.

Customizing the Restart Classloader

As described earlier in the Restart vs Reload section, restart functionality is implemented by using two classloaders. If this causes issues, you can diagnose the problem by using the spring.devtools.restart.enabled system property, and if the app works with restart switched off, you might need to customize what gets loaded by which classloader.

By default, any open project in your IDE is loaded with the “restart” classloader, and any regular .jar file is loaded with the “base” classloader. The same is true if you use mvn spring-boot:run or gradle bootRun: the project containing your @SpringBootApplication is loaded with the “restart” classloader, and everything else with the “base” classloader. The classpath is printed on the console when you start the app, which can help to identify any problematic entries. Classes used reflectively, especially annotations, can be loaded into the parent (fixed) classloader on startup before the application classes which use them, and this might lead to them not being detected by Spring in the application.

You can instruct Spring Boot to load parts of your project with a different classloader by creating a META-INF/spring-devtools.properties file. The spring-devtools.properties file can contain properties prefixed with restart.exclude and restart.include. The include elements are items that should be pulled up into the “restart” classloader, and the exclude elements are items that should be pushed down into the “base” classloader. The value of the property is a regex pattern that is applied to the classpath passed to the JVM on startup. Here is an example where some local class files are excluded and some extra libraries are included in the restart class loader:

restart.exclude.companycommonlibs="/mycorp-common-[\\w\\d-\\.]/(build|bin|out|target)/"
restart.include.projectcommon="/mycorp-myproj-[\\w\\d-\\.]+\\.jar"
All property keys must be unique. As long as a property starts with restart.include. or restart.exclude. it is considered.
All META-INF/spring-devtools.properties from the classpath are loaded. You can package files inside your project, or in the libraries that the project consumes. System properties can not be used, only the properties file.

Known Limitations

Restart functionality does not work well with objects that are deserialized by using a standard ObjectInputStream. If you need to deserialize data, you may need to use Spring’s ConfigurableObjectInputStream in combination with Thread.currentThread().getContextClassLoader().

Unfortunately, several third-party libraries deserialize without considering the context classloader. If you find such a problem, you need to request a fix with the original authors.