1
votes

I am using spring boot (v1.5.3.BUILD-SNAPSHOT) I am new to spring boot.

Using gradle

Note that the normal thymeleaf dialect works fine (th:...) spring-boot-starter-thymeleaf\1.5.3.BUILD-SNAPSHOT

I want to add thymeleaf-layout-dialect I added the dependency

compile('nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect')

the documentation says to add the dialect by doing the following

TemplateEngine templateEngine = new TemplateEngine();  // Or 
SpringTemplateEngine for Spring config
templateEngine.addDialect(new LayoutDialect());

So i added a configuration class

@Configuration
public class MyConfiguration {


@Bean
public SpringTemplateEngine templateEngine(){
    SpringTemplateEngine templateEngine  = new SpringTemplateEngine();
    templateEngine.addDialect(new LayoutDialect());
    return templateEngine;
}
}

but when I try running the app I get the following error

org.thymeleaf.exceptions.ConfigurationException: Cannot initialize: no template resolvers have been set
at org.thymeleaf.Configuration.initialize(Configuration.java:203) ~[thymeleaf-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.thymeleaf.TemplateEngine.initialize(TemplateEngine.java:827) ~[thymeleaf-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.thymeleaf.spring4.view.ThymeleafView.renderFragment(ThymeleafView.java:203) ~[thymeleaf-spring4-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.thymeleaf.spring4.view.ThymeleafView.render(ThymeleafView.java:190) ~[thymeleaf-spring4-2.1.5.RELEASE.jar:2.1.5.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1282) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1037) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:980) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) ~[spring-webmvc-4.3.8.BUILD-SNAPSHOT.jar:4.3.8.BUILD-SNAPSHOT]

Can someone tell me how to add the thymeleaf-layout-dialect correctly?

1
could you check if this helps: stackoverflow.com/questions/43197416/… - Tommy Schmidt

1 Answers

0
votes

The issue is:

org.thymeleaf.exceptions.ConfigurationException: Cannot initialize: no template resolvers have been set

To integrate Thymeleaf with Spring, you need to configure 3 beans:

  • ThymeleafViewResolver Bean - You would be set it with a template engine
  • SpringTemplateEngine Bean - You would be set it with a template resolver
  • TemplateResolver Bean

In your templateEngine bean you didn't set any template resolver, so you might change your templateEngine() method as following:

@Bean
public SpringTemplateEngine templateEngine(TemplateResolver templateResolver){
    SpringTemplateEngine templateEngine  = new SpringTemplateEngine();
    templateEngine.setTemplateResolver(templateResolver);       
    templateEngine.addDialect(new LayoutDialect());
    return templateEngine;
}

Spring will provide you with a templateResolver bean of SpringTemplateEngine.


BTW If you define spring-boot-starter-thymeleaf as dependency, it will provide thymeleaf-layout-dialect as a dependency with the convenient version, then Spring will use ThymeleafAutoConfiguration.java - Spring Boot 1.5.x to configure a default beans for the three required beans.

For example:

LayoutDialect bean is define here ThymeleafWebLayoutConfiguration.ThymeleafWebLayoutConfiguration():

@Configuration
@ConditionalOnClass(name = "nz.net.ultraq.thymeleaf.LayoutDialect")
protected static class ThymeleafWebLayoutConfiguration {

    @Bean
    @ConditionalOnMissingBean
    public LayoutDialect layoutDialect() {
        return new LayoutDialect();
    }

}

SpringTemplateEngine bean is defined with a template resolver and dialect from here ThymeleafWebLayoutConfiguration.ThymeleafDefaultConfiguration():

@Configuration
@ConditionalOnMissingBean(SpringTemplateEngine.class)
protected static class ThymeleafDefaultConfiguration {

  private final Collection<ITemplateResolver> templateResolvers;

  private final Collection<IDialect> dialects;

  public ThymeleafDefaultConfiguration(
      Collection<ITemplateResolver> templateResolvers,
      ObjectProvider<Collection<IDialect>> dialectsProvider) {
    this.templateResolvers = templateResolvers;
    this.dialects = dialectsProvider.getIfAvailable();
  }

  @Bean
  public SpringTemplateEngine templateEngine() {
    SpringTemplateEngine engine = new SpringTemplateEngine();
    for (ITemplateResolver templateResolver : this.templateResolvers) {
      engine.addTemplateResolver(templateResolver);
    }
    if (!CollectionUtils.isEmpty(this.dialects)) {
      for (IDialect dialect : this.dialects) {
        engine.addDialect(dialect);
      }
    }
    return engine;
  }

}

And finally a thymeleafViewResolver bean is defined here AbstractThymeleafViewResolverConfiguration.thymeleafViewResolver():

@Bean
@ConditionalOnMissingBean(name = "thymeleafViewResolver")
@ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
public ThymeleafViewResolver thymeleafViewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    configureTemplateEngine(resolver, this.templateEngine);
    resolver.setCharacterEncoding(this.properties.getEncoding().name());
    resolver.setContentType(appendCharset(this.properties.getContentType(),
        resolver.getCharacterEncoding()));
    resolver.setExcludedViewNames(this.properties.getExcludedViewNames());
    resolver.setViewNames(this.properties.getViewNames());
    // This resolver acts as a fallback resolver (e.g. like a
    // InternalResourceViewResolver) so it needs to have low precedence
    resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
    resolver.setCache(this.properties.isCache());
    return resolver;
}

which is extended by ThymeleafAutoConfiguration.Thymeleaf2ViewResolverConfiguration:

@Bean
@ConditionalOnMissingBean(name = "thymeleafViewResolver")
@ConditionalOnProperty(name = "spring.thymeleaf.enabled", matchIfMissing = true)
public ThymeleafViewResolver thymeleafViewResolver() {
    ThymeleafViewResolver resolver = new ThymeleafViewResolver();
    configureTemplateEngine(resolver, this.templateEngine);
    resolver.setCharacterEncoding(this.properties.getEncoding().name());
    resolver.setContentType(appendCharset(this.properties.getContentType(),
        resolver.getCharacterEncoding()));
    resolver.setExcludedViewNames(this.properties.getExcludedViewNames());
    resolver.setViewNames(this.properties.getViewNames());
    // This resolver acts as a fallback resolver (e.g. like a
    // InternalResourceViewResolver) so it needs to have low precedence
    resolver.setOrder(Ordered.LOWEST_PRECEDENCE - 5);
    resolver.setCache(this.properties.isCache());
    return resolver;
}

Hope it is clear now.