I tried all tips and tricks that I found here and in docs, but still no luck. I have Spring webapp with Thymeleaf. Resources and templates are not reloaded when I call update in IDEA (it says nothing to reload). I can then press ctrl+f5 in a browser like crazy, changes are just not there.
Everything is configured in one Java class like this:
@EnableWebMvc public class MvcConfig extends WebMvcConfigurerAdapter implements ApplicationContextAware {
My folder structure now looks like this, but I also tried to put the resources without “static” folder or to webapp/resources.
ResourceHandlerRegistry:
@Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { super.addResourceHandlers(registry); registry.addResourceHandler("/img/**").addResourceLocations("classpath:/static/img/"); registry.addResourceHandler("/css/**").addResourceLocations("classpath:/static/css/"); registry.addResourceHandler("/js/**").addResourceLocations("classpath:/static/js/"); }
I specified cache=false in both application.properties:
spring.thymeleaf.cache=false
and in mentioned MvcConfig class:
@Bean public SpringResourceTemplateResolver templateResolver() { SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver(); templateResolver.setApplicationContext(this.applicationContext); templateResolver.setPrefix("/WEB-INF/templates/"); templateResolver.setSuffix(".html"); templateResolver.setTemplateMode(TemplateMode.HTML); templateResolver.setCacheable(false); return templateResolver; }
According to some answers on SO i added dependency for devtools:
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <version>1.4.1.RELEASE</version> <optional>true</optional> </dependency>
Still not working. Some said to add maven boot plugin with addResources=true, so I did:
<plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>1.4.1.RELEASE</version> <configuration> <addResources>true</addResources> </configuration> </plugin>
My Idea is set properly I guess, because when I call update, my Java classes are reloaded immediately. Only resources and html files are not, I must restart server for it. Actualy *.html files are not so big a deal, but to restart server after every small css and js change is slowing me down a lot, and as I lost almost 15 hours figuring out what is wrong, it started to be really frustrating.
Any help will be greatly appreciated.
Advertisement
Answer
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 🙂