Skip to main content

Spring Boot DevTools

Introduction

Spring Boot DevTools (Developer Tools) is a set of tools that aims to make the development experience more pleasant. As a developer, you want to focus on writing code rather than waiting for your application to restart or manually refreshing your browser. Spring Boot DevTools addresses these pain points by providing features like automatic restarts, live reload, and more.

In this tutorial, we'll explore how Spring Boot DevTools can significantly improve your development workflow and productivity.

What is Spring Boot DevTools?

Spring Boot DevTools is a module that includes a set of additional development-time features to make the development experience more convenient. The main features include:

  1. Automatic restart - When files on the classpath change, the application automatically restarts
  2. Live reload - Browser refresh when resources change
  3. Property defaults - Sensible development-time property defaults
  4. Remote applications - Support for remote debugging

Getting Started with Spring Boot DevTools

Adding DevTools to Your Project

To add DevTools to your Spring Boot project, include the following dependency in your pom.xml file:

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 this to your build.gradle file:

groovy
developmentOnly 'org.springframework.boot:spring-boot-devtools'

Automatic Restart

One of the most valuable features of DevTools is automatic restart. When you make changes to your application code, DevTools automatically restarts your application.

Spring Boot uses two classloaders:

  • Base classloader: Loads unchanging dependencies (like third-party JARs)
  • Restart classloader: Loads your application code that often changes during development

When DevTools detects a change, only the restart classloader is reloaded, making restarts much faster than a complete application restart.

Let's see a simple example:

  1. Create a simple REST controller:
java
@RestController
public class HelloController {

@GetMapping("/hello")
public String sayHello() {
return "Hello, DevTools!";
}
}
  1. Run your Spring Boot application
  2. Access the endpoint at http://localhost:8080/hello
  3. Now modify the controller:
java
@RestController
public class HelloController {

@GetMapping("/hello")
public String sayHello() {
return "Hello, Updated DevTools!"; // Changed text
}
}
  1. Once you save the file, DevTools will automatically restart your application
  2. Refresh your browser, and you'll see the updated message

Excluding Resources from Trigger

Sometimes you might want to exclude certain resources from triggering a restart. You can configure this in your application.properties or application.yml file:

properties
spring.devtools.restart.exclude=static/**,public/**

This will prevent changes to files in the static and public directories from triggering a restart.

Disabling Automatic Restart

If you want to disable automatic restart completely:

properties
spring.devtools.restart.enabled=false

Live Reload

DevTools includes an embedded LiveReload server that is used to trigger a browser refresh when a resource is changed. To utilize this feature:

  1. Ensure LiveReload is enabled (it is by default):
properties
spring.devtools.livereload.enabled=true
  1. Install the LiveReload browser extension for your browser (Chrome, Firefox, etc.)

When you make changes to static resources (HTML, CSS, JavaScript), templates, or even application code (which triggers a restart), your browser will automatically refresh after the changes are processed.

Global Settings

DevTools supports global settings via a file at ~/.spring-boot-devtools.properties. Properties defined in this file will apply to all Spring Boot applications on your machine that use DevTools.

For example:

properties
# Global DevTools settings
spring.devtools.restart.poll-interval=2s
spring.devtools.restart.quiet-period=1s

Remote Development

DevTools also includes support for remote application development. This is disabled by default for security reasons but can be useful when deploying to a remote environment.

To enable remote support, update your configuration:

properties
spring.devtools.remote.secret=mysecret

And then include the remote DevTools dependency:

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

Property Defaults

DevTools sets several properties to values that are more suitable for development. For example:

  • Disabling template caching for Thymeleaf, FreeMarker, etc.
  • Setting the H2 console to enabled
  • Setting logging levels for web requests to DEBUG

Here's a comparison of some properties with and without DevTools:

PropertyWithout DevToolsWith DevTools
spring.thymeleaf.cachetruefalse
spring.freemarker.cachetruefalse
spring.mustache.cachetruefalse
spring.web.resources.cache.perioddepends on content type0 (no caching)
logging.level.webINFODEBUG

Real-World Example: Developing a Todo Application

Let's build a simple Todo application to demonstrate how DevTools enhances the development workflow:

  1. First, create a basic Todo entity:
java
@Entity
public class Todo {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

private String title;
private boolean completed;

// Getters and setters

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public boolean isCompleted() {
return completed;
}

public void setCompleted(boolean completed) {
this.completed = completed;
}
}
  1. Create a repository:
java
@Repository
public interface TodoRepository extends JpaRepository<Todo, Long> {
}
  1. Create a controller:
java
@RestController
@RequestMapping("/api/todos")
public class TodoController {

private final TodoRepository todoRepository;

public TodoController(TodoRepository todoRepository) {
this.todoRepository = todoRepository;
}

@GetMapping
public List<Todo> getAllTodos() {
return todoRepository.findAll();
}

@PostMapping
public Todo createTodo(@RequestBody Todo todo) {
return todoRepository.save(todo);
}
}
  1. Run your application and test the endpoints

Now, imagine you want to add a new endpoint to delete a Todo. With DevTools, you can:

  1. Add the new method to your controller:
java
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteTodo(@PathVariable Long id) {
todoRepository.deleteById(id);
return ResponseEntity.ok().build();
}
  1. As soon as you save the file, DevTools will automatically restart your application
  2. You can immediately test the new endpoint without manually restarting

Similarly, if you're working on the front-end:

  1. Create an HTML template at src/main/resources/templates/index.html:
html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<title>Todo App</title>
<link rel="stylesheet" href="/css/styles.css">
</head>
<body>
<h1>Todo List</h1>
<ul id="todos">
<!-- Todos will be inserted here -->
</ul>
<script src="/js/app.js"></script>
</body>
</html>
  1. Create a CSS file at src/main/resources/static/css/styles.css:
css
body {
font-family: Arial, sans-serif;
max-width: 800px;
margin: 0 auto;
padding: 20px;
}
h1 {
color: #333;
}
  1. Create a JavaScript file at src/main/resources/static/js/app.js:
javascript
// Fetch todos from the API
fetch('/api/todos')
.then(response => response.json())
.then(todos => {
const todoList = document.getElementById('todos');
todos.forEach(todo => {
const li = document.createElement('li');
li.textContent = todo.title;
if (todo.completed) {
li.style.textDecoration = 'line-through';
}
todoList.appendChild(li);
});
});

With LiveReload enabled, any changes you make to these files will automatically refresh your browser, making front-end development much smoother.

Best Practices for Using DevTools

  1. Only use DevTools in development: Configure your build to exclude DevTools in production

    For Maven:

    xml
    <build>
    <plugins>
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
    <excludeDevtools>true</excludeDevtools>
    </configuration>
    </plugin>
    </plugins>
    </build>
  2. Tune restart options: Customize which files trigger restarts based on your workflow

  3. Combine with JRebel: If you need more sophisticated hot reloading

  4. Be aware of property defaults: DevTools changes certain default properties that should not be used in production

  5. Use LiveReload plugins: Install the browser extensions to get the most from the LiveReload feature

Common Issues and Troubleshooting

Automatic Restart Not Working

  1. Make sure DevTools is correctly added to your dependencies
  2. Verify that automatic restart is not disabled in application.properties
  3. Check if the changes you make are in a location that triggers restarts

LiveReload Not Working

  1. Make sure the LiveReload browser extension is installed and enabled
  2. Verify that LiveReload is enabled in application.properties
  3. Check browser console for any connection errors

Application Restarts Too Frequently

If your application restarts too often, you can customize the trigger file patterns:

properties
spring.devtools.restart.exclude=static/**,public/**,META-INF/resources/**

Summary

Spring Boot DevTools significantly enhances the developer experience by providing:

  • Automatic application restart when code changes
  • Browser LiveReload when resources change
  • Development-appropriate property defaults
  • Remote development support

These features collectively reduce development time and friction, allowing you to focus on writing code rather than waiting for restarts or manually refreshing your browser.

Additional Resources

Exercises

  1. Create a new Spring Boot application and add DevTools. Experiment with making changes to see the automatic restart in action.
  2. Configure DevTools to exclude certain directories from triggering restarts.
  3. Set up a frontend with Thymeleaf and observe how DevTools affects template caching.
  4. Create a global DevTools configuration file with custom settings.
  5. Try enabling remote DevTools support and connect to a remote application.


If you spot any mistakes on this website, please let me know at [email protected]. I’d greatly appreciate your feedback! :)