Tuesday, December 6, 2016

Spring Boot and Thymeleaf: Reload templates and static resources without restarting the application

Thymeleaf was designed around the concept of Natural Templates that allows static prototyping: template logic doesn’t affect the template from being used as prototype. Although this is a great technique, you may also want to see the results in a running Spring Boot application and without restarting the server each time you change Thymeleaf view. In addition, you may expect that all other static resources like JavaScript and CSS files can be reloaded during development also. How to achieve it with Spring Boot?

Thymeleaf templates reloading

While working on a Spring Boot application that is utilizing Thymeleaf view engine two properties are needed in order to ensure reloading templates: spring.thymeleaf.cache and spring.thymeleaf.prefix. Setting spring.thymeleaf.cache to false disables template caching whereas spring.thymeleaf.prefix allows specifying prefix that gets prepended to view names when building a view URL.

Example (Windows):

spring.thymeleaf.prefix=file:///C:/Projects/github/spring-boot-thymeleaf/src/main/resources/templates/

Assuming the all templates are in the path specified, changing them will require a page refresh but not application / server restart.

Both properties can be used in a development profile (e.g. create application-dev.properties and run the application with dev profile active).

Reload static resources (CSS, JavaScript)

With Spring Boot and Thymeleaf reloading templates during development is relatively easy. If you want to achieve reloading of static resources like CSS and JavaScript the approach is very similar: you need to use spring.resources.static-locations.

Example (Windows):

spring.resources.static-locations=file:///C:/Projects/github/spring-boot-thymeleaf//src/main/resources/static/

In the above example there is a single location, but the property accepts multiple locations.

Furthermore, you can configure more settings related to static resources, like for example caching etc. Please refer to Spring Boot documentation and find out about spring.resources.* properties (http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html)

application-dev.properties

The final solution could look like below:

#
# Development profile with templates and static resources reloading
#

# Path to project
project.base-dir=file:///C:/Projects/github/spring-boot-thymeleaf

# Templates reloading during development
spring.thymeleaf.prefix=${project.base-dir}/src/main/resources/templates/
spring.thymeleaf.cache=false

# Static resources reloading during development
spring.resources.static-locations=${project.base-dir}/src/main/resources/static/
spring.resources.cache-period=0

Note: You will find it in the source code reference in this article: HOW-TO: Spring Boot and Thymeleaf with Maven

If you don’t want to create new profile, you can simply provide properties as JVM options (-D) while running the application.

Alternative approach - Spring Boot DevTools

One of the modules of Spring Boot is the DevTools (as of version 1.3). Among many features it enables live reloading Thymeleaf templates and static resources without any further configuration. It has also support for LiveReload protocol.

Note: When you change the template / resource rebuild the project (CTRL+F9 on Windows) and then refresh. When you install LiveReload plugin (I tested with LiveReload plugin for Chrome: https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei) after rebuild the page gets refreshed automatically.

Find out more here: https://spring.io/blog/2015/06/17/devtools-in-spring-boot-1-3 and here: https://t.co/td23nP73mt

Summary

You can make frontend development of the Spring Boot application much easier thanks to the techniques described in this article. But possibility of serving Thymeleaf templates and static resources of your Spring Boot application from outside the classpath in production could bring some advantages too. One of the example could be separating backend and frontend deployments.

See also

8 comments:

  1. project.base-dir=file:///C:/Projects/github/spring-boot-thymeleaf

    this line is ridiculous, it means that your project will be able to build only from a single location)) so study how include thymeleaf instead of breaking spring boot with redefined vars

    ReplyDelete
    Replies
    1. Thanks for very gentle comment ;)

      Pushing this to repo indeed may sound ridiculous but this is just an example to give an idea. I provide this property via CLI while developing.

      And please share your idea of doing this better.

      Delete
    2. An alternative is to use a relative path like this:

      spring.thymeleaf.prefix: file:./src/main/resources/templates/

      Just make sure that your working directory is set correctly.

      Delete
    3. An alternative is to use a ralative URL like this:

      spring.thymeleaf.prefix: file:./src/main/resources/templates/

      Just make sure your working directory is correct.

      Delete
  2. Hey,

    The cache false property work only if we are using an IDE like eclipse or intellij. IF we are running the application from terminal using maven e,g, mvn clean install tomcat7:run with tomcat server, it does not work. Please do let me know if this works without IDE.

    Thanks,
    Chirag

    ReplyDelete
    Replies
    1. Hello,

      The described approach will work outside the IDE.

      Run the Spring Boot application using Spring Boot plugin (either Maven or Gradle).

      Delete
  3. Thanks Rafa, it worked like a charm :)

    ReplyDelete
  4. Great tutorial...
    for universal URL many OS

    spring.thymeleaf.prefix: file:./src/main/resources/templates/

    ReplyDelete