avatarDwen

Summary

Understanding hot deployment and hot reloading in Spring Boot can improve development and debugging efficiency, with solutions provided by the Spring Boot Devtools plugin.

Abstract

This article discusses hot deployment and hot reloading in Spring Boot, emphasizing the benefits of using the Spring Boot Devtools plugin for faster development and debugging. Hot deployment and hot reloading enable automatic updates to the application while it's running. The article also distinguishes between hot deployment, which directly reloads the entire application, and hot reloading, which upgrades the application by reloading classes at runtime. LiveLoad, a tool for automatic loading and updating browser clients, is also introduced. The article then delves into the configuration of Devtools for hot deployment, using POM and IDEA settings, as well as configuring application.yml. The principle of Devtools and its automatic restart functionality is explained, followed by a discussion on its packaging into JAR, remote debugging capabilities, and disabling cache options by default. The article concludes by mentioning alternatives to Devtools in development processes.

Opinions

  • The Spring Boot team provides the Devtools plugin to improve development and debugging efficiency.
  • Hot deployment and hot reloading can automatically update the application while it's running, with hot deployment being more thorough and time-consuming, and hot reloading being faster but less clean.
  • LiveLoad, a tool for automatic browser client updates, is integrated with Devtools and supports Chrome, Firefox, and Safari.
  • Devtools uses two class loaders, with one loading classes that won't change and the other loading classes that will change, allowing for faster restarts.
  • By default, Devtools is not packaged into a JAR and is disabled when running a packaged application, but it supports remote debugging for debugging applications remotely.
  • Devtools disables cache options by default to prevent caching from hindering the changes made in the application.
  • Alternatives to Devtools in development processes include JRebel and manual restarts, as well as using Rebuild in IDEA for hot-updating modified class files.

Understanding Hot Deployment and Hot Reloading in Spring Boot

Spring Boot hot deployment and hot reloading

Photo by Milk-Tea on Unsplash

In Spring Boot development and debugging, if we need to restart and debug each line of code modification, it may be time-consuming.

The Spring Boot team provides the spring-boot-devtools (Short name: Devtools) plugin for this problem, which tries to improve the efficiency of development and debugging.

What are hot deployment and hot reloading?

Hot deployment and hot reloading can automatically update (reload or replace classes, etc.) the application while the application is running.

Note: The solution provided by spring-boot-devtools also needs to be restarted, but it can be automatically loaded without a manual restart.

Strictly speaking, we need to distinguish between hot deployment and hot loading. For Java projects:

1. Hot deployment

  • Redeploy the project while the server is running.
  • It directly reloads the entire application, frees up memory, is cleaner and more thorough than hot reloading, and takes more time.

2. Hot loading

  • Reloads the class at runtime to upgrade the application.
  • The implementation principle of hot loading mainly depends on the class loading mechanism of java. The implementation method can be summarized as starting a background thread when the container starts and regularly detecting the change of the timestamp of the class file. If the timestamp of the class changes, the Class reloads.
  • Compared with the reflection mechanism, reflection obtains class information at runtime and changes program behavior through dynamic calls; hot loading is changing class information at runtime by reloading and directly changing program behavior.

What is LiveLoad?

LiveLoad is a tool that provides automatic loading and updating of browser clients. It is divided into two parts: LiveLoad Server and LiveLoad Browser plug-in.

The LiveLoad server has been integrated with devtools, so if we are developing a web application and expect the browser to refresh automatically, we can consider LiveLoad now.

Only one LiveReload server can be running at the same time.

Before starting the application, make sure that no other LiveReload servers are running.

If multiple applications are launched from the IDE, only the first application will support LiveReload.

Configure devtools for hot deployment

1. POM configuration

Add the dependency of spring-boot-devtools.

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <optional>true</optional> <!-- Can prevent passing devtools dependencies into other modules -->
    </dependency>
</dependencies>

2. IDEA configuration

If you use IDEA development tools, there are usually two ways:

Method 1: When there is no configuration, manually trigger the restart update (Ctrl+F9).

You can also use mvn compile to trigger a restart update.

Method 2: IDEA needs to enable runtime compilation and automatically restart and update.

First select File -> Setting -> Build,Execution,Deployment -> Compile .

Then, check the Make project automatically.

Shortcut key: ctrl + alt + shift + / , Select Registry , check the compiler.automake.allow.when.app.running .

The new version of IDEA can be set as the first in File -> Setting -> Advanced Settings .

application.yml configuration

spring:
  devtools:
    restart:
      enabled: true  # Set to enable hot deployment
      additional-paths: src/main/java # restart directory
      exclude: WEB-INF/**
  thymeleaf:
    cache: false # Use Thymeleaf template engine, turn off caching

Using LiveLoad

The spring-boot-devtools module contains an embedded LiveReload server that can be used to trigger browser refreshes when resources change.

The LiveReload browser extension supports Chrome, Firefox, and Safari, and you can download it for free from https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei.

Or download from the browser plugin center, such as Firefox:

After installation, it can be managed through the following icons.

You can set the spring.devtools.livereload property to false if you do not want to start the LiveReload server while the application is running.

Only one LiveReload server can be running at a time. Please make sure that no other LiveReload servers are running before starting the application.

If multiple applications are launched from the IDE, only the first application will support LiveReload.

The Principle of Devtool? Why Does It Automatically Restart?

spring-boot-devtools uses two class loaders: one ClassLoader loads classes that will not change (third-party jar packages), and the other ClassLoader (restart ClassLoader) loads classes that will change (custom classes).

A file monitoring thread is started in the background. When the files in the monitored directory change, the original Restart ClassLoader is discarded, and the new Restart ClassLoader will be reloaded.

Because the third-party jar package is not reloaded after the file is changed, only the custom classes are loaded, and the loaded classes are relatively few, so the restart is faster.

This is why the same is to restart the application. Why not manually restart? It is recommended to use spring-boot-devtoolsfor hot deployment restart.

There are a few things to be aware of during automatic restarts:

  • An automatic restart will log.

It can be turned off by the following configuration.

spring:
  devtools:
    restart:
      log-condition-evaluation-delta: false
  • Exclude some resources that do not need an automatic restart.

Certain resources do not necessarily need to trigger a restart when they change.

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, exclude only /static, /public you would set the following properties:

spring:
  devtools:
    restart:
      exclude: "static/**,public/**"

If you want to keep these defaults and add additional exclusions, use the spring.devtools.restart.additional-exclude property instead.

  • Custom restart classloader.

The restart function is implemented by using two class loaders. For most applications, this approach works well. However, it sometimes causes classloading issues.

By default, any open project in the IDE is loaded with the “restart” classloader, and any regular .jar files are loaded with the “base” classloader. You may need to customize something if you work on a multi-module project and not every module is imported into your IDE. To do this, you can create a meta-inf/spring-devtools.properties file.

The spring-devtools.properties file can contain properties prefixed with restart.exclude and restart.include.

The included element is the item that should be pulled up to the “restart” class loader, and the excluded element is the item that should be pushed down to the “Base” class loader.

The value of this property is a regular expression pattern applied to the classpath, as shown in the following example:

restart:
  exclude:
    companycommonlibs: "/mycorp-common-[\\w\\d-\\.]+\\.jar"
  include:
    projectcommon: "/mycorp-myproj-[\\w\\d-\\.]+\\.jar"

Will Devtool Be Packaged Into Jar?

By default, it will not be packaged into a JAR.

The developer tools are automatically disabled when running a packaged application. If you start it through java-jar or other special class loaders, it will be considered as a production environment application.

If we expect to debug the application remotely, In this case, Devtool is also capable of remote debugging: remote client applications are designed to be run from within your IDE.

You need org.springframework.boot.devtool.RemoteSpringApplication to run with the same classpath as the remote project, you are connecting to.

The only required parameter for the application is the remote URL to which it connects.

For example, if using Eclipse or Spring Tools, and you have a project named my-app that has been deployed to Cloud Foundry, do the following:

  • Select Run Configurations…​ from the Run menu.
  • Create a new Java Application, “Launch Configuration.”
  • Browse the my-app project.
  • Use org.springframework.boot.devtools.RemoteSpringApplication as the main class.
  • Add https://myapp.cfapps.io to Program arguments (or whatever your remote URL is).

Why Does Devtool Disable the Cache Option by Default?

Some libraries supported by Spring Boot use caching to improve performance. For example, template engines cache compiled templates to avoid repeated parsing of template files. Additionally, Spring MVC can add HTTP cache headers to responses when serving static resources.

While caching is very beneficial in production, it can be counterproductive during development, preventing you from seeing the changes you just made in your application. For this reason, spring-boot-devtools disables the cache option by default.

For example, Thymeleaf provides spring.thymeleaf.cache to set the cache of the template engine. When using the spring-boot-devtools module, you do not need to manually set these properties, because spring-boot-devtools will set them automatically.

So what configuration will be automatically set? You can find the corresponding default configuration in the DevToolsPropertyDefaultsPostProcessor class.

public class DevToolsPropertyDefaultsPostProcessor implements EnvironmentPostProcessor {

 static {
  Map<String, Object> properties = new HashMap<>();
  properties.put("spring.thymeleaf.cache", "false");
  properties.put("spring.freemarker.cache", "false");
  properties.put("spring.groovy.template.cache", "false");
  properties.put("spring.mustache.cache", "false");
  properties.put("server.servlet.session.persistent", "true");
  properties.put("spring.h2.console.enabled", "true");
  properties.put("spring.web.resources.cache.period", "0");
  properties.put("spring.web.resources.chain.cache", "false");
  properties.put("spring.template.provider.cache", "false");
  properties.put("spring.mvc.log-resolved-exception", "true");
  properties.put("server.error.include-binding-errors", "ALWAYS");
  properties.put("server.error.include-message", "ALWAYS");
  properties.put("server.error.include-stacktrace", "ALWAYS");
  properties.put("server.servlet.jsp.init-parameters.development", "true");
  properties.put("spring.reactor.debug", "true");
  PROPERTIES = Collections.unmodifiableMap(properties);
 }

Of course, if you don’t want the application properties to be set by spring-boot-devtools by default, you can pass spring.devtools.add-properties to false in your application.yml.

Can Devtools Do the Global Configuration for All Spring Boot Applications?

Global Devtools settings can be configured by adding the spring-boot-devtools.yml file to the $HOME/.confg/spring-boot directory.

Any properties added to these files will apply to all Spring Boot applications using Devtools on your machine. For example, to configure restart to always use the trigger file, you need to add the following property to your spring-boot-devtools file:

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

If I Don’t Use Devtool, What Are My Options?

In the actual development process, I will not use the Devtool tool, because:

  • Devtool itself is based on the restart method, which is still not a real hot-replacement solution, JRebel is (it is charged).
  • If the overhead of automatic restart is not much different from the manual restart, then it is better to restart manually (restart on demand).
  • In most cases, if it is an internal modification of a method or a modification of static resources, it can be hot-updated through Rebuild (Ctrl + Shift + F9) in IDEA.
  • In addition, there is a tool spring loaded, which can realize the hot deployment of modified class files. For details, please refer to the instructions on its GitHub address.

Thank you for reading this article.

Stay tuned for more.

Programming
Java
Software Development
Spring Boot
Software Engineering
Recommended from ReadMedium