Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Thymeleaf templates cache even when spring.template.cache: false #34

Closed
checketts opened this issue Aug 23, 2013 · 30 comments
Closed

Thymeleaf templates cache even when spring.template.cache: false #34

checketts opened this issue Aug 23, 2013 · 30 comments

Comments

@checketts
Copy link
Contributor

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.

@ukitzmann
Copy link

You can use this to disable the Thymeleaf cache:

spring.thymeleaf.cache: false

@checketts
Copy link
Contributor Author

This ticket is noting that even when using that property, they are being cached.

@dsyer
Copy link
Member

dsyer commented Sep 18, 2013

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.

@dsyer
Copy link
Member

dsyer commented Sep 20, 2013

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?

@yanhua365
Copy link

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.

@dsyer dsyer closed this as completed Sep 27, 2013
@MattFriedman
Copy link

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.

@dsyer
Copy link
Member

dsyer commented Nov 2, 2014

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.

@MattFriedman
Copy link

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.

@dsyer
Copy link
Member

dsyer commented Nov 4, 2014

"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).

@snicoll
Copy link
Member

snicoll commented Nov 4, 2014

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.

@pieterdegraeuwe
Copy link

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...

@amr
Copy link

amr commented Dec 28, 2014

@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.

@dsyer
Copy link
Member

dsyer commented Dec 28, 2014

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).

@thesurlydev
Copy link

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.

@jgon
Copy link

jgon commented Jun 29, 2015

@amr : Thank you.
The solution using the ThymeleafConfiguration worked perfectly.
I just had to replace @Inject by @Autowired in my case.

@giovannicandido
Copy link

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

@henryabra
Copy link

@giovannicandido Thanks for the tip.
One note though, ${resources.projectroot} did not work for me but ${user.dir} worked like a charm.
Cheers

@snicoll
Copy link
Member

snicoll commented Jan 27, 2016

@henryabra ${resources.projectroot} is a custom key that is defined in the same yml file (see the two first line).

@henryabra
Copy link

@giovannicandido You are absolutely correct.

@oak1980
Copy link

oak1980 commented Jul 19, 2017

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

@checketts
Copy link
Contributor Author

@oak1980 You are using a debug configuration and hitting CTRL-F9? (See #34 (comment)) What versions of SpringBoot are you using if you believe it is a regression?

@oak1980
Copy link

oak1980 commented Jul 19, 2017

With this approach, I don't need to press CTRL-F9.

@checketts
Copy link
Contributor Author

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)

@PhaneendraNakkala
Copy link

@oak1980 you are awesome!
that works like charm.

@anuragphadke19
Copy link

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

@attacomsian
Copy link

I recommend using Gulp to automate templates and resources reload. Following is a little Gulp task that does the magic for me:

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 on this topic as well.

@pdurejachd
Copy link

pdurejachd commented Jan 5, 2020

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;
    }
}

@waltervi
Copy link

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!

@dtonhofer
Copy link

dtonhofer commented Jul 16, 2023

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

@alfuguo
Copy link

alfuguo commented Apr 21, 2024

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~ 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests