If I write a test that loads a template under src/main/resources/templates
it works fine. If I then create a template under src/test/resources/templates
the test then fails as the template loader switches to looking there and only there. It's useful to be able to have a test template to check the behaviour of any custom Freemarker settings.
Ideally it would load from all templates
resources found on the classpath, not just one.
Project to reproduce the problem (Spring Boot 2.4.0-M2): https://github.com/halfninja/spring-ftl-bug-repro
Renaming src/test/resources/templates
causes the test to pass.
Comment From: snicoll
Thanks for the report but this is working as documented. Templates are picked up from a single directory so you creating an extra one means Spring Boot will look there and only there.
There is a note in the documentation that hints you at using classpath*
to search every templates
directory. It's a bit too IDE specific at the moment so let's reuse this issue to improve the documentation.
Comment From: halfninja
Thanks for the swift response and link to the docs, makes sense. Couldn't actually get the demo test to pass using classpath*
- I may just add a second template path specifically for test templates, to avoid the collision.
Comment From: snicoll
Sorry for overlooking the sample. That is interesting and it looks like it is Freemarker specific. I'll have to dig in a little bit more and we can requalify this issue accordingly. Given the loader is in the spring framework we may also create an issue there if need to be.
I may just add a second template path specifically for test templates, to avoid the collision.
Regardless of fixing this issue, I find that setup more explicit.
Comment From: snicoll
So with the help of @jhoeller I've been able to dig into this problem. The core framework support of Freemarker default to look for a single directory if available (see preferFileSystemAccess
on FreeMarkerConfigurationFactory
). In this particular sample, when the test runs in the IDE, a directory is found (spring-ftl-bug-repro/build/resources/test/templates/
) so it defaults to that and doesn't use the classpath at all. That explains why the template in the other classpath location isn't considered.
This flag is true
by default to support templates reloading. In the context of Spring Boot, I am not sure that's what we want. Flagging for team attention to see if the rest of the team agrees.
Also, the notes that I've shared above doesn't qualify for Freemarker at least. Freemarker will ignore classpath*
style so we may want to revisit this note as well.
Comment From: philwebb
The documentation note was added in the fix for #2319
Comment From: snicoll
There is actual a property that controls this that was introduced in #2901
@halfninja I've added spring.freemarker.prefer-file-system-access=false
to application.properties
in your sample and the test passed. Please add this property in your project (if you still need two templates directories with the same name). We've decided to flip the default value of the property to false
in 2.4.x
so that this use case you've described works out-of-the-box.