Reputation: 2069
I'm building a SpringBoot app that loads internationalisation messages from Database. (Followed this tutorial)
From that, I had to create a ThymeleafConfiguration class and set a SpringTemplateEngine Bean. The tutorial gave only a rough idea about this configuration (only configured the message source, but not the other templateengine configurations), so it broke my controller page rendering (controller is now returning string instead of view).
I'm trying to configure the rest of my TemplateEngine (such as the TemplateResolver, which I think is the reason why the rendering is not correct), however, I can't figure out how to do it correctly [I keep getting "An error happened during template parsing (template: "ServletContext resource [/templates/login.html]")" messages].
How to configure SpringTemplateEngine correctly?
My configuration so far:
@Configuration
public class ThymeleafConfiguration implements WebMvcConfigurer, ApplicationContextAware{
private ApplicationContext applicationContext;
@Autowired
private DatabaseMessageSource databaseMessageSource;
@Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver resolver = new ThymeleafViewResolver();
resolver.setTemplateEngine(thymeleafTemplateEngine());
resolver.setCharacterEncoding("UTF-8");
return resolver;
}
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/templates/");
resolver.setSuffix(".html");
resolver.setTemplateMode(TemplateMode.HTML);
return resolver;
}
@Bean
public SpringTemplateEngine thymeleafTemplateEngine() {
SpringTemplateEngine engine = new SpringTemplateEngine();
engine.setTemplateResolver(templateResolver());
engine.setTemplateEngineMessageSource(databaseMessageSource);
return engine;
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
Controller class:
@Controller
public class ApplicationController {
@RequestMapping("/home")
public String home() {
return "/home.html";
}
@RequestMapping("/core/index")
public String index() {
return "/core/index.html";
}
@RequestMapping("/login")
public String login() {
return "login";
}
Upvotes: 1
Views: 2421
Reputation: 544
Another example in case someone wants a working reference:
@Configuration
public class ThymeleafConfig implements InitializingBean {
public static final String TEMPLATE_LOCATION = "classpath:/thymeleaf/templates/email/";
protected static final Logger logger = CustomLoggerFactory.getLogger();
@Autowired
private ApplicationContext applicationContext;
@Bean
public SpringTemplateEngine emailTemplateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(htmlTemplateResolver());
templateEngine.setTemplateResolver(textTemplateResolver());
return templateEngine;
}
private SpringResourceTemplateResolver htmlTemplateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setOrder(Integer.valueOf(1));
templateResolver.setPrefix(TEMPLATE_LOCATION);
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCharacterEncoding(StandardCharsets.UTF_8.toString());
templateResolver.setCacheable(false);
templateResolver.setCheckExistence(true);
return templateResolver;
}
private SpringResourceTemplateResolver textTemplateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setOrder(Integer.valueOf(2));
templateResolver.setPrefix(TEMPLATE_LOCATION);
templateResolver.setSuffix(".txt");
templateResolver.setTemplateMode(TemplateMode.TEXT);
templateResolver.setCharacterEncoding(StandardCharsets.UTF_8.toString());
templateResolver.setCacheable(false);
templateResolver.setCheckExistence(true);
return templateResolver;
}
@Override
public void afterPropertiesSet() throws Exception {
// this just prints the templates found
String path = TEMPLATE_LOCATION;
ClassPathResource resource = new ClassPathResource(path);
try (InputStream inputStream = resource.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
logger.info("Found the following templates in " + path);
String line;
while ((line = reader.readLine()) != null) {
logger.info(line);
}
} catch (Exception e) {
logger.error("Caught Exception listing email templates:" + e.toString());
}
}
}
Upvotes: 0
Reputation: 2069
The problem is with
private ITemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("/templates/"); // Here!!!
resolver.setSuffix(".html");
return resolver;
}
Since the templates are within src/main/resources, it has to be pointed to classpath, as follows:
@Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
resolver.setApplicationContext(applicationContext);
resolver.setPrefix("classpath:/templates/"); // It works after adding 'classpath:'
resolver.setSuffix(".html");
return resolver;
}
Also, there's a little change from the interface to a implementation class that should not interfere with the result.
Upvotes: 3