Using Spring Boot's DevTools for hot code reloading

Developers are always looking for ways to speed things up. Long ago, one of the biggest speedups was incremental compilers and having them run every time we saved a file. Now that it's permeated modern tools, no one thinks twice about such a feature.

Something critically needed when it comes to building Spring Boot apps is the ability to detect a change in our code and relaunch the embedded container.

Thankfully, we just need one addition to our code we built in the previous chapter:

    compile("org.springframework.boot:spring-boot-devtools") 
If you happen to be using Maven, you would want to include the optional flag.

So, this tiny module performs the following activities:

  • Disables cache settings for autoconfigured components
  • When it detects a change in code, it restarts the application, holding onto third-party classes and simply throwing away and reloading custom classes
  • Activates an embedded LiveReload (http://livereload.com/) server that can trigger the browser to refresh the page automatically

For a listing of all the disabled components, look at the following code snippet:

    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.session.persistent", "true"); 
    properties.put("spring.h2.console.enabled", "true"); 
    properties.put("spring.resources.cache-period", "0"); 
    properties.put("spring.resources.chain.cache", "false"); 
    properties.put("spring.template.provider.cache", "false"); 
    properties.put("spring.mvc.log-resolved-exception", "true"); 
    properties.put("server.servlet.jsp.init-parameters.development",
"true"); properties.put("spring.reactor.stacktrace-mode.enabled", "true");
Many IDEs also come with additional reloading support when apps are run in the debug mode, a highly recommended option to use in conjunction with Spring Boot DevTools.

What is the net benefit, you ask?

When we make a change to our code and either issue a Save or a Make Project, DevTools will throw away the class loader holding our custom code and launch a new application context. This makes for a relatively speedy restart.

Save or Make Project? Spring Boot DevTools listens for file updates. For certain IDEs, such as Eclipse, ⌘-S is used to perform a Save operation. IntelliJ IDEA autosaves, so an alternative signal is Make Project, ⌘-F9, which refreshes the environment.

With the LiveReload server running and a LiveReload plugin (http://livereload.com/extensions/) installed in our browser, we can enable LiveReloading upon visiting the site. Anytime we update the code, the plugin will essentially click the browser's refresh button for us.

Restarting versus reloading: DevTools provides the ability to restart the application quickly, but it is limited in various ways. For example, updating the classpath by adding new dependencies is not picked up. Adding new classes isn't supported. For more sophisticated tools that handle these complex use cases, you may wish to investigate something such as Spring Loaded (https://github.com/spring-projects/spring-loaded) or JRebel (http://zeroturnaround.com/software/jrebel/).

With all these caches cleared out, we can see changes propagate much faster. Let's test it out by launching LearningSpringBootApplication in the debug mode. If we visit the site, things look as expected:

The site starts off with our pre-loaded test data. To have the browser listen for updates, we need to click the LiveReload icon:

At first, the dot in the center is hollow. When enabled, the dot turns solid, as shown in the preceding screenshot.

Let's make some edits to our template:

With this extra sub-header, we just need to hit Save or Make Project in our IDE. Switching to the browser will show the results instantly:

Let's make some tweaks to HomeController as shown here:

    @GetMapping("/") 
    public Mono<String> index(Model model) { 
      model.addAttribute("images", 
        imageService.findAllImages()); 
      model.addAttribute("extra", 
        "DevTools can also detect code changes too"); 
      return Mono.just("index"); 
    } 

This is the same as the previous chapter, except that we have added a new attribute, extra, to the model. We can display it with an adjustment to our template:

    <h4 th:text="${extra}"></h4> 

This displays the new extra model attribute as an H4 header, all without clicking a thing in our browser:

There is one key side effect when using Spring Boot DevTools for restarts-- any in-memory data or state will be lost.

That can be good or bad. It certainly encourages you to create a pre-loader, perhaps with a @Profile("dev") annotation such that it only runs when spring.profiles.active=dev is switched on.

This can become an issue if our use case takes a lot of steps to set up, and restarting the app makes us repeat these steps again and again. This is amplified by in-memory database solutions such as H2. In our situation, the start-up code that cleans out the uploaded files will cause a similar refresh of data.

Another reason to consider NOT switching on LiveReload in the browser (yet let the app restart) is if we are working on a JavaScript-heavy frontend and don't want every change to force a reload. For example, we might have a page with a lot of fields filled out. A triggered restart may clean out our form and force us to re-enter the data.

Nevertheless, this is a good problem to have. Having the option to refresh the browser and stay in sync with code changes is a powerful tool.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset