Spring boot and Thymeleaf - Hot swap templates and resources once again

Here are my settings with IntelliJ IDEA (2018.3), it's reload HTML after the changes are saved:

  1. In application.properties:

    spring.resources.static-locations = classpath:/resources/static
    spring.resources.cache.period = 0
    
  2. In pom.xml, set <addResources>true</addResources>

    <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <addResources>true</addResources>
        </configuration>
    </plugin>
    
  3. Menu Run => Edit Configurations (IntelliJ IDEA)

On frame deactivation: Update resources


I have spent some time on it and finally here I'll explain how I got it working. Googling around you may find several info:

  • Spring Boot hot swap
  • SO - Spring Boot + Jetty & hot deployment
  • SO - Netbeans 8 won't reload static Thymeleaf files

My inital approach was to disable caching and add Spring dev tools:

Spring boot application.properties

spring.thymeleaf.cache=false
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.prefix=/templates/

pom.xml

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

Using the snippet above however is not enough since the hot swap is done only when making the project (CTRL + F9 in Intellij Idea). This is due to the fact that the default template resolver is classpath based and that's the reason a recompilation is necessary.


A working solution is to override the defaultTemplateResolver by using a file system based resolver:

application.properties

spring.thymeleaf.cache=false
spring.thymeleaf.mode=LEGACYHTML5
spring.thymeleaf.templates_root=src/main/resources/templates/

Application class

@SpringBootApplication
public class MyApplication {

    @Autowired
    private ThymeleafProperties properties;

    @Value("${spring.thymeleaf.templates_root:}")
    private String templatesRoot;

    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }

    @Bean
    public ITemplateResolver defaultTemplateResolver() {
        FileTemplateResolver resolver = new FileTemplateResolver();
        resolver.setSuffix(properties.getSuffix());
        resolver.setPrefix(templatesRoot);
        resolver.setTemplateMode(properties.getMode());
        resolver.setCacheable(properties.isCache());
        return resolver;
    }
}

I find this solution optimal since it allow you to externalize the configuration and use different profiles (dev, prod, etc..) while having the benefit of reloading the changes by just pressing F5 :)