When editing Thymeleaf templates, a server restart is required to view the updates.
Even with the following setting in application.properties:
# Allow Thymeleaf templates to be reloaded at dev time
spring.template.cache: false
To reproduce:
With spring-boot-sample-web-ui, run it with mvn spring-boot:run and edit any of the templates, they don't reload after server has been started.
Comment From: ukitzmann
You can use this to disable the Thymeleaf cache:
spring.thymeleaf.cache: false
Comment From: checketts
This ticket is noting that even when using that property, they are being cached.
Comment From: dsyer
mvn spring-boot:run probably runs from the compiled jar. To use spring.template.cache: false effectively you need to launch from an IDE. Does that make sense? It seems to work for other people.
Comment From: dsyer
I guess if you mvn package you will get the source files copied into the classpath of the running process. If that works I'm not sure what else we can do. Did you try it?
Comment From: yanhua365
It works!
I user IntelliJ Idea debug the application.
After add application.properties with:
spring.thymeleaf.cache: false
Then,after edit html template, must use CTRL+F9 to make the project.
In this way,it works fine for me.
Comment From: MattFriedman
I run the application from main() in Idea IDE. I set the application.properties as stated above.
If I'm using jsp then I can expect changes to the jsp files to be visible immediately without recompiling.
I think the issue here is that there is an expectation that the thymeleaf templates will have the same behaviour. This does not appear to be the case.
Is it possible to have changes to the th templates visible any time they are changed, without any recompiling or rebuilding of the project?
The point is that front-end developers need to make tons of changes to templates and view the results often. Having to recompile every time is a ton of overhead for a front-end developer so they want to avoid this.
Comment From: dsyer
Well it works for other people so you must be doing something different, I'd say. Did you read everything above? E.g. you seem to be using the wrong property name for the cache setting.
Comment From: MattFriedman
Hi Dave,
I have done the following: I read all the posts. I put the system in debug (running from main()) and verified that the TemplateResolver/ViewResolver had caching set to false. I used both properties mentioned above, both set to false. I tried changing the template and opened the page in two separate browsers to see if it was the browser that was caching the older version but this is not the case. I checked using curl as well.
I think what it comes down to is how you define: "it works"
Above, yanhua365 says "Then,after edit html template, must use CTRL+F9 to make the project"
For me, "it works" means: change the template => refresh browser => changes are visible.
So yanhua365 is correct, it does work in the way he describes. However, as far as I can determine, it does not work in the way I am describing.
I'm just trying to point out that the intermediate step of having to rebuild is a problem as it adds a boatload of overhead to the development flow for front-end developers. Front-end developers are constantly making changes and then refreshing the page to check the result. (to the point of developing repetitive stress injuries) Adding an intermediate step is a problem from that perspective.
I don't know if it possible for it to work in the way I'm describing, but if it is it would be a great improvement.
Comment From: dsyer
"CTRL+F9" must be something you can automate (build on save or something). Other IntelliJ users manage it, so it must be possible (cc @snicoll in case he knows what the incantation is).
Comment From: snicoll
https://www.jetbrains.com/idea/documentation/migration_faq.html
You can enable automatic compilation on every save (or autosave). To do that, turn on the Make project automatically option on the Compiler page in the Settings / Preferences dialog (File | Settings | Compiler on Windows or Linux, or IntelliJ IDEA | Preferences | Compiler on Mac OS X).
@MattFriedman if you want to discuss this further, please create a separate issue.
Comment From: pieterdegraeuwe
For the ones that are struggling with this too. Be sure that your application.properties is on the right location! (more on this here) When you have in your resources directory also a sub directory 'templates', it can be quickly overseen that your application.properties is not IN, but on the same level as the 'resourses' directory. At least this was the case for me on a late evening.... I discovered it by putting the application.properties in a config directory... then the reloading did suddenly work.. This lead me to see that the other application.properties was not found, since it was not in the resources directory...
Comment From: amr
@MattFriedman The default template resolver registered by spring is classpath based, meaning that it loads the templates from the compiled resources. That's why it requires a recompilation. Thymeleaf includes a file-system based resolver, this loads the templates from the file-system directly not through the classpath (compiled resources). Spring Boot allows us to override the default resolver by making a bean with the name defaultTemplateResolver, here is a full example:
@Configuration
public class ThymeleafConfiguration {
@Bean
public ITemplateResolver defaultTemplateResolver() {
TemplateResolver resolver = new FileTemplateResolver();
resolver.setSuffix(".html");
resolver.setPrefix("path/to/your/templates");
resolver.setTemplateMode("HTML5");
resolver.setCharacterEncoding("UTF-8");
resolver.setCacheable(false);
return resolver;
}
}
With this, I basically Ctrl+S and refresh the browser. A better variation would be one that uses ThymeleafProperties, like that:
@Configuration
public class ThymeleafConfiguration {
@Inject
private ThymeleafProperties properties;
@Value("${spring.thymeleaf.templates_root:}")
private String templatesRoot;
@Bean
public ITemplateResolver defaultTemplateResolver() {
TemplateResolver resolver = new FileTemplateResolver();
resolver.setSuffix(properties.getSuffix());
resolver.setPrefix(templatesRoot);
resolver.setTemplateMode(properties.getMode());
resolver.setCharacterEncoding(properties.getEncoding());
resolver.setCacheable(properties.isCache());
return resolver;
}
}
This would work with an application-dev.yml like:
spring:
thymeleaf:
mode: HTML5
cache: false
templates_root: src/main/resources/templates/
In my application, I annotate that resolver with @Profile(Constants.SPRING_PROFILE_DEVELOPMENT) to limit its use to development. That's why I also set the caching to false in the configuration file (it's -dev only). In production I use the default classpath-based loader.
Comment From: dsyer
You should be able to just use the default classpath loader as long as you are running in debug mode (and your IDE is configured to copy resources on save - Eclipse does this out of the box).
Comment From: thesurlydev
For other folks that might run into this issue. I had the same problem until I realized that IntelliJ's key mapping for Ctrl-F9 was not actually doing what it was supposed to (Make Project). You can verify this in a couple of ways: 1. monitor the timestamp of a Thymeleaf template in target/classes/templates after you make a change and use Ctrl-F9. 2. make a change to a template, then use the Build > Make Project via the main menu.
The fix for my particular case was to remap the keyboard shortcut for "Make Project". After I did this I was able to make changes to my templates, use my new keyboard shortcut for "Make Project", then reload the browser to see the changes.
Comment From: jgon
@amr : Thank you. The solution using the ThymeleafConfiguration worked perfectly. I just had to replace @Inject by @Autowired in my case.
Comment From: giovannicandido
In my application-development.yml:
resources:
projectroot: /Users/giovanni/Projects/projectName
spring:
thymeleaf:
cache: false
prefix: file:///${resources.projectroot}/server/src/main/resources/templates/
This way in development it use the direct files, and in production the classpath Note: There is a subproject named server in the projectName project root
Comment From: henryabra
@giovannicandido Thanks for the tip.
One note though, ${resources.projectroot} did not work for me but ${user.dir} worked like a charm.
Cheers
Comment From: snicoll
@henryabra ${resources.projectroot} is a custom key that is defined in the same yml file (see the two first line).
Comment From: henryabra
@giovannicandido You are absolutely correct.
Comment From: oak1980
Springboot with IntelliJ and configurations in src/main/resources/application.properties I put in the following relative path, and started the Application.main(...) from IntelliJ:
# Templates reloading during development
spring.thymeleaf.prefix=file:src/main/resources/templates/
spring.thymeleaf.cache=false
# Static resources reloading during development
spring.resources.static-locations=file:src/main/resources/static/
spring.resources.cache-period=0
Comment From: checketts
@oak1980 You are using a debug configuration and hitting CTRL-F9? (See https://github.com/spring-projects/spring-boot/issues/34#issuecomment-24964507) What versions of SpringBoot are you using if you believe it is a regression?
Comment From: oak1980
With this approach, I don't need to press CTRL-F9.
Comment From: checketts
Ah so you are reporting an alternative approach that works for you and avoids the need to rebuild in IntelliJ.
It is good to call out that you wouldn't want to check it spring.resources.static-locations=file:src/main/resources/static/ in your application.yml, and instead set it via a run config in intelliJ so you don't accidentally check it in (or perhaps set it in a profile specific file)
Comment From: PhaneendraNakkala
@oak1980 you are awesome! that works like charm.
Comment From: anuragphadke19
Springboot with IntelliJ and configurations in src/main/resources/application.properties I put in the following relative path, and started the Application.main(...) from IntelliJ:
```
Templates reloading during development
spring.thymeleaf.prefix=file:src/main/resources/templates/ spring.thymeleaf.cache=false
Static resources reloading during development
spring.resources.static-locations=file:src/main/resources/static/ spring.resources.cache-period=0 ```
If someone else drop's by this long-closed issue, the parameter should be(as of Spring Boot 2.0.5 release)
spring.resources.cache.period=0
Comment From: attacomsian
I recommend using Gulp to automate templates and resources reload. Following is a little Gulp task that does the magic for me:
```javascript var gulp = require('gulp'), watch = require('gulp-watch');
gulp.task('watch', function () { return watch('src/main/resources//.', () => { gulp.src('src/main/resources/') //replace with build/resources/main/ for netBeans .pipe(gulp.dest('out/production/resources/')); }); });
gulp.task('default', ['watch']);
I wrote a short [blog post](https://attacomsian.com/blog/spring-boot-auto-reload-thymeleaf-templates/) on this topic as well.
**Comment From: pdurejachd**
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
```java
@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;
}
}
Comment From: waltervi
Springboot with IntelliJ and configurations in src/main/resources/application.properties I put in the following relative path, and started the Application.main(...) from IntelliJ:
```
Templates reloading during development
spring.thymeleaf.prefix=file:src/main/resources/templates/ spring.thymeleaf.cache=false
Static resources reloading during development
spring.resources.static-locations=file:src/main/resources/static/ spring.resources.cache-period=0 ```
You saved my day buddy!
Comment From: dtonhofer
The latest configuration names seem to be as follows, based off Spring Boot 3.1.0:
Unchanged:
# Templates reloading during development
spring.thymeleaf.prefix=file:src/main/resources/templates/
spring.thymeleaf.cache=false
Changed:
# Static resources reloading during development
spring.web.resources.static-locations=file:src/main/resources/static/
spring.web.resources.cache.period=0
Or in YAML (application.yml):
spring:
thymeleaf:
# Template reloading during development
prefix: file:src/main/resources/templates/
cache: false
web:
resources:
# Static resource reloading during development
static-locations: file:src/main/resources/static/
cache:
period: 0
Comment From: alfuguo
The latest configuration names seem to be as follows, based off Spring Boot 3.1.0:
Unchanged:
```
Templates reloading during development
spring.thymeleaf.prefix=file:src/main/resources/templates/ spring.thymeleaf.cache=false ```
Changed:
```
Static resources reloading during development
spring.web.resources.static-locations=file:src/main/resources/static/ spring.web.resources.cache.period=0 ```
Or in YAML (
application.yml):
spring: thymeleaf: # Template reloading during development prefix: file:src/main/resources/templates/ cache: false web: resources: # Static resource reloading during development static-locations: file:src/main/resources/static/ cache: period: 0
Thank you @dtonhofer, still working in 2024~ 👍