Spring Boot Developer Tools

An application server is needed when developing web applications with Java. And often, we need to restart the server to pick up our changes. This kills productivity, as server restart - depends on the size of application will take some times.

Spring Boot introduced Spring Boot Developer Tools feature in the 1.3.0 release to address these common tasks.This new module provides solutions to automatically pick up changes without a complete server restart. This feature make developer’s life a lot easier and improving productivity in building Spring Web Applications.

Add Spring Boot Developer Tools to your project by including this dependency to your Spring Boot Project Maven's pom.xml:

<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency>

Or if you're using Gradle, add to your build.gradle:

dependencies { compile("org.springframework.boot:spring-boot-devtools") }

Automatic Restart

Using spring-boot-devtools, whenever files change in the classpath, applications using spring-boot-devtools will cause the application to restart. It shorten the time to verify the changes.

2019-10-11 07:22:31.596 INFO 16040 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : Devtools property defaults active! Set 'spring.devtools.add-properties' to 'false' to disable 2019-10-11 07:22:31.596 INFO 16040 --- [ restartedMain] .e.DevToolsPropertyDefaultsPostProcessor : For additional web related logging consider setting the 'logging.level.web' property to 'DEBUG' 2019-10-11 07:22:41.630 INFO 16040 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode. 2019-10-11 07:22:41.699 INFO 16040 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 32ms. Found 0 repository interfaces. 2019-10-11 07:22:43.260 INFO 16040 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9af9dd99] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2019-10-11 07:22:46.980 INFO 16040 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2019-10-11 07:22:47.326 INFO 16040 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2019-10-11 07:22:47.326 INFO 16040 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.24] 2019-10-11 07:22:48.213 INFO 16040 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2019-10-11 07:22:48.214 INFO 16040 --- [ restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 16617 ms 2019-10-11 07:22:51.371 INFO 16040 --- [ restartedMain] o.s.s.concurrent.ThreadPoolTaskExecutor : Initializing ExecutorService 'applicationTaskExecutor' 2019-10-11 07:22:52.534 WARN 16040 --- [ restartedMain] ion$DefaultTemplateResolverConfiguration : Cannot find template location: classpath:/templates/ (please add some templates or check your Thymeleaf configuration) 2019-10-11 07:22:55.064 INFO 16040 --- [ restartedMain] .s.s.UserDetailsServiceAutoConfiguration : Using generated security password: ab9ef4db-41d6-417c-bb5e-9b4590a47b34 2019-10-11 07:22:56.188 INFO 16040 --- [ restartedMain] o.s.s.web.DefaultSecurityFilterChain : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@286d1e8a, org.springframework.security.web.context.SecurityContextPersistenceFilter@3e50abb, org.springframework.security.web.header.HeaderWriterFilter@114ed77a, org.springframework.security.web.csrf.CsrfFilter@7be59389, org.springframework.security.web.authentication.logout.LogoutFilter@744c7bd5, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@31192745, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@574ad209, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@2090389, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@24ddd392, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@1c1fa3bd, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@3fd4555b, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3aac23a3, org.springframework.security.web.session.SessionManagementFilter@42ab730d, org.springframework.security.web.access.ExceptionTranslationFilter@3be54ea3, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@4db1fe1] 2019-10-11 07:22:56.353 INFO 16040 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729 2019-10-11 07:22:56.438 INFO 16040 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path '' 2019-10-11 07:22:56.441 INFO 16040 --- [ restartedMain] c.d.m.MeetingDashboardApplication : Started MeetingDashboardApplication in 32.79 seconds (JVM running for 39.795) 2019-10-11 07:26:18.836 INFO 16040 --- [ Thread-6] o.s.s.concurrent.ThreadPoolTaskExecutor : Shutting down ExecutorService 'applicationTaskExecutor' . ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v2.1.8.RELEASE) 2019-10-11 07:26:19.264 INFO 16040 --- [ restartedMain] c.d.m.MeetingDashboardApplication : Starting MeetingDashboardApplication on DessonAr with PID 16040 (D:\Projects\github\spring-boot-quickstart\meeting-dashboard\target\classes started by Desson in D:\Projects\github\spring-boot-quickstart\meeting-dashboard) 2019-10-11 07:26:19.264 INFO 16040 --- [ restartedMain] c.d.m.MeetingDashboardApplication : No active profile set, falling back to default profiles: default 2019-10-11 07:26:19.600 INFO 16040 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Bootstrapping Spring Data repositories in DEFAULT mode. 2019-10-11 07:26:19.608 INFO 16040 --- [ restartedMain] .s.d.r.c.RepositoryConfigurationDelegate : Finished Spring Data repository scanning in 8ms. Found 0 repository interfaces. 2019-10-11 07:26:19.677 INFO 16040 --- [ restartedMain] trationDelegate$BeanPostProcessorChecker : Bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' of type [org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration$$EnhancerBySpringCGLIB$$9af9dd99] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying) 2019-10-11 07:26:19.863 INFO 16040 --- [ restartedMain] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8080 (http) 2019-10-11 07:26:19.864 INFO 16040 --- [ restartedMain] o.apache.catalina.core.StandardService : Starting service [Tomcat] 2019-10-11 07:26:19.864 INFO 16040 --- [ restartedMain] org.apache.catalina.core.StandardEngine : Starting Servlet engine: [Apache Tomcat/9.0.24] 2019-10-11 07:26:20.137 INFO 16040 --- [ restartedMain] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring embedded WebApplicationContext 2019-10-11 07:26:20.137 INFO 16040 --- [ restartedMain] o.s.web.context.ContextLoader : Root WebApplicationContext: initialization completed in 869 ms

From above logs, do notice the thread is a "restartedMain" thread - not a main thread (Refer to Spring Boot Quick Start to see the sample of main thread).

Triggering a restart in an IDE

The goal is for any changes made in the project, be it a java file change will cause an automated restart of the project. However, this varies depending on your IDE. It is not enough to just change your .java files, but the IDE needs to update .class files on the classpath. The restart is triggered whenever change detected on the classpath.

In Eclipse it is enough just to save your files.

In NetBeans is to make sure "Compile on Save" is checked in Project Properties -> Build -> Compile:

NetBeans Project Properties - Build - Compile

NetBeans Project Properties - Build - Compile

When using IntelliJ IDEA, you need to configure IDEA to rebuild automatically or to change Spring Boot run configuration and define what happens when you trigger an application update.

Enable/Disable Logging of Auto-configuration Changes

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.

2019-10-11 08:10:41.252 INFO 19548 --- [ restartedMain] .ConditionEvaluationDeltaLoggingListener : Condition evaluation unchanged

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

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

Using a Trigger File

Frequent automatic restarts may not be desirable on every file change and even can slower down development time. To solve this problem, 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 Spring Boot Devtools has detected it has changes for a restart (ex: file changes in classpath).

Use spring.devtools.restart.trigger-file property to mention the trigger file for your application. It can be any external or internal file.

spring.devtools.restart.trigger-file=restart.now

On above example, check for restart will triggered when the src/main/resources/restart.now is updated.


Spring Boot Starter 1.3.0 released in November 2015. Before that, the available solution in the market is JRebel, a product of ZeroTurnaround. According to their site "JRebel is an anything-Java plugin that speeds up JVM-based development (Java, Scala, Groovy) by reloading changes made in your workspace into a running JVM, without restarts or redeploys, maintaining the state of the application while you’re coding." ZeroTurnaround refers to this technology as "hotpatching" or sometimes "dynamic app reloading."