Home > Software engineering >  How to use TWO SpringResourceTemplateResolver Beans?
How to use TWO SpringResourceTemplateResolver Beans?

Time:11-04

Since Thymeleaf 3, Thymeleaf prefers the use of SpringResourceTemplateResolver (https://www.thymeleaf.org/doc/articles/thymeleaf3migration.html). So I decided to go from ClassLoaderTemplateResolver to SpringResourceTemplateResolver:

@Configuration
@EnableWebMvc
public class MvcConfig implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("classpath:/static/");
        registry.setOrder(1);
    }

    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("/templates/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding("UTF-8");
        resolver.setOrder(0);
        resolver.setCheckExistence(true);
        return resolver;
    }

    @Bean
    public SpringResourceTemplateResolver templateResolver2() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("/templates-2/");
        resolver.setSuffix(".html");
        resolver.setTemplateMode(TemplateMode.HTML);
        resolver.setCharacterEncoding("UTF-8");
        resolver.setOrder(1);
        resolver.setCheckExistence(true);
        return resolver;
    }
}

Unfortunately, when implementig like this, I'll get an error: Error resolving template [index], template might not exist or might not be accessible by any of the configured Template Resolvers.

To be honest, I've simple replaced ClassLoaderTemplateResolver with SpringResourceTemplateResolver in the hope, this will work. It doesn't. But searching for a working solution dealing with two template locations, all I find are outdated samples using ClassLoaderTemplateResolvers.

Trying to implement the code snippet provided by Thymeleaf as shown here https://www.thymeleaf.org/doc/articles/thymeleaf3migration.html won't work either when using two template directories, besides the fact, that this code itself uses the deprecated WebMvcConfigurerAdapter.

Is there any example how to configure a Spring Boot application using Thymeleaf having two or more template locations which isn't completely outdated?

CodePudding user response:

So after a while and many many tryouts I've finally got the templates working. Since there isn't any decent answer to my question flying round the internet, I will post my solution for others:

@Configuration
public class ThymeleafConfig implements ApplicationContextAware {

    private ApplicationContext applicationContext;

    @Override
    public void setApplicationContext(@Autowired ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Bean
    public SpringResourceTemplateResolver templateResolver() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.applicationContext);
        templateResolver.setPrefix("classpath:/templates-1/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setOrder(1);
        templateResolver.setCheckExistence(true); /* FYI: necessary to chain TemplateResolvers */
        templateResolver.setCacheable(false);     /* FYI: during development -> false, so that we can see changes we make */
        return templateResolver;
    }

    @Bean
    public SpringResourceTemplateResolver templateResolver2() {
        SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
        templateResolver.setApplicationContext(this.applicationContext);
        templateResolver.setPrefix("classpath:/templates-2/");
        templateResolver.setSuffix(".html");
        templateResolver.setTemplateMode(TemplateMode.HTML);
        templateResolver.setCharacterEncoding("UTF-8");
        templateResolver.setOrder(2);
        templateResolver.setCheckExistence(true); /* FYI: necessary to chain TemplateResolvers */
        templateResolver.setCacheable(false);     /* FYI: during development -> false, so that we can see changes we make */
        return templateResolver;
    }

    @Bean
    public SpringTemplateEngine templateEngine() {
        /* SpringTemplateEngine automatically applies SpringStandardDialect and
           enables Spring's own MessageSource message resolution mechanisms. */
        SpringTemplateEngine templateEngine = new SpringTemplateEngine();

        templateEngine.addTemplateResolver(this.templateResolver());
        templateEngine.addTemplateResolver(this.templateResolver2());

        templateEngine.setEnableSpringELCompiler(true);
        return templateEngine;
    }

    @Bean
    public ViewResolver viewResolver() {
        ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
        viewResolver.setTemplateEngine(this.templateEngine());
        viewResolver.setCharacterEncoding("UTF-8");
        viewResolver.setCache(false);   /* FYI: during development -> false */
        viewResolver.setOrder(1);
        return viewResolver;
    }
}

I hope this will help others to save time and nerves^^.

CodePudding user response:

If you are using Spring Boot, you can add an extra resolver on top of the default one like this:

First, add this to application.properties:

# This ensures that the default HTML template resolver of Thymeleaf has priority over our custom SVG resolver
spring.thymeleaf.template-resolver-order=0

Then add the extra resolver in a @Configuration class:

@Configuration
public class MyApplicationConfiguration {

    @Bean
    public ITemplateResolver svgTemplateResolver() {
        SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setPrefix("classpath:/templates/svg/");
        resolver.setSuffix(".svg");
        resolver.setTemplateMode("XML");

        return resolver;
    }
}

There is no need to manually define SpringTemplateEngine and ViewResolver beans.

You can disable caching during development using spring.thymeleaf.cache=false.

  • Related