Display messages with thymeleaf in Spring Boot - spring-boot

I'm tryting to add externalized messages from a properties file in a thymeleaf html template. I have a file messages_es.properties located in i18n/messages with this inside:
estimado=Estimado:
In my html template i have the following
<div th:text="#{estimado}">Estimado placeholder</div>
but then, the html I get is the following:
<div>??estimado_es??</div>
Is anyone able to help me?
This is the configuration i have added in order to make this work:
#Bean
#Qualifier("custom")
public ITemplateResolver thymeleafTemplateResolver(){
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML");
templateResolver.setCharacterEncoding("UTF-8");
return templateResolver;
}
#Bean
public SpringTemplateEngine thymeleafTemplateEngine(#Qualifier("custom") ITemplateResolver templateResolver) {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.setTemplateResolver(templateResolver);
templateEngine.setTemplateEngineMessageSource(messageSource());
return templateEngine;
}
#Bean
#Description("Spring Message Resolver")
public ResourceBundleMessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("i18n/messages");
return messageSource;
}
In my application.yml file:
spring.messages.basename: i18n/messages

first of all you should add classpath: as prefix to your base name.
secondly if you have baseName set toi18n/messages app will look for i18n/messages_es.properties
if i understand correctly your file path is i18n/messages/messages_es.properties
so you need to set baseName to: classpath:i18n/messages/messages

Related

WebMvcTest when Multiple TemplateResolver

I have added a second TemplateResolver because I would like to use also Thymeleaf to serve Template for Plain-Text Templates. When starting application it works fine, the Thymeleaf templates are being resolved.
But from now my #WebMvcTests are not working. I says, that:
Error resolving template [disclaimer/view], template might not exist or might not be accessible by any of the configured Template Resolvers
The TemplateResolver are configures like:
#Configuration
public class SitemapViewResolverConfiguration {
#Bean
public ITemplateResolver thymeleafTextTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("/templates/sitemap/");
templateResolver.setCacheable(false);
templateResolver.setSuffix(".txt");
templateResolver.setTemplateMode(TemplateMode.TEXT);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCheckExistence(TRUE);
return templateResolver;
}
}
#Configuration
public class PageViewResolverConfiguration {
#Bean
public ITemplateResolver thymeleafHtmlTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("classpath:/templates/view/");
templateResolver.setCacheable(false);
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCheckExistence(TRUE);
return templateResolver;
}
}
My template structure is as follows:
The test class is:
#RunWith(SpringRunner.class)
#WebMvcTest(DisclaimerController.class)
public class DisclaimerControllerTest {
#Autowired MockMvc mvc;
#Test
public void testGet() throws Exception {
mvc.perform(get("/disclaimer")
.andExpect(status().isOk())
.andExpect(view().name("disclaimer/view"))
;
}
}
Error:
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.thymeleaf.exceptions.TemplateInputException: Error resolving template [disclaimer/view], template might not exist or might not be accessible by any of the configured Template Resolvers
Okay, I found the problem. As I use #WebMvcTest it didn't load my TemplateResolver. As before I relied on Spring Boot automatic resolver, I am using now two selfmade resolver. But they are not picked up by the test, that's why MockMvc could not resolve it.
I fixed it by adding Configuration as Import:
#RunWith(SpringRunner.class)
#WebMvcTest({PageViewResolverConfiguration.class, DisclaimerController.class})
public class DisclaimerControllerTest {
...
}

What is the difference between SpringResourceTemplateResolver and ClassLoaderTemplateResolver?

I'm trying to cofigure my project. I have two variants of tempalteResolver.
if i use this one:
#Bean
public SpringResourceTemplateResolver templateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setApplicationContext(applicationContext);
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCacheable(true);
return templateResolver;
}
i get an error that my template can't resolve the thymeleaf syntax th even when i add xmlns:th="http://www.thymeleaf.org"
and when i use the following code:
#Bean
public ClassLoaderTemplateResolver templateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("/WEB-INF/templates/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCacheable(false);
templateResolver.setCharacterEncoding("UTF-8");
return templateResolver;
}
i get an error that there is no templates under this path (/WEB-INF/templates).
Full path to my templates is src\main\webapp\WEB-INF\templates\
What is the best template resolver to be used and why?
Thanks!
You should be using SpringResourceTemplateResolver for web projects (using SpringMvc controllers), and ClassLoaderTemplateResolver for command line projects, or when you need to generate html for non-web applications (such as sending html email or something like that).
First error occured becouse spring security somehow didn't connect to a project and my
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
modelAndView.addObject("auth", auth);
Send nulls.
And second error i dunno why occured.

Adding new view resolver

I created a module in a Spring-boot project and I want to redirect a controller to a view in this module. I can't find a solution and I've been trying different options. Now, I'm adding template resolvers in my WebMvcConfig and the one to the root templates is working but I can't make the other one work. Any idea please?
Here is the WebMvcConfig:
#Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
#Bean
public ClassLoaderTemplateResolver templateModuleResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("espmonitor/src/main/resources/templates/");
templateResolver.setCacheable(false);
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
templateResolver.setCharacterEncoding("UTF-8");
return templateResolver;
}
#Bean
public ClassLoaderTemplateResolver templateRootResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/");
templateResolver.setCacheable(false);
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
templateResolver.setCharacterEncoding("UTF-8");
return templateResolver;
}
#Bean
public SpringTemplateEngine templateEngine() {
SpringTemplateEngine templateEngine = new SpringTemplateEngine();
templateEngine.addTemplateResolver(templateModuleResolver());
templateEngine.addTemplateResolver(templateRootResolver());
return templateEngine;
}
#Bean
public ViewResolver viewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(templateEngine());
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}
The view controller is:
#RequestMapping("/index_esp_monitor")
public String espMonitor(Model model){
return "index_esp_monitor";
}
My project structure:
I managed to make it work and I'm going to show the solution here just in case someone is trying to do a similar thing.
I was trying to have many applications within one project and trying to have each application in a different module.
First, I created the modules in the project and add an additional module as a selector. Then I remove the src folder from the project and add the modules to the project pom
<modules>
<module>espmonitor</module>
<module>seed</module>
<module>selector</module>
</modules>
And the pom of each module contains:
<parent>
<artifactId>SeedCert</artifactId>
<groupId>com.niab</groupId>
<version>0.0.1</version>
</parent>
The project structure is as follows, the module selector will contain the indexes to the other modules.
The Application.java is configured to scan the configurations of the other modules.
#ComponentScan({
"com.niab.config",
"com.niab.selector.controller"
})
Each module has a com.niab.config package for the specific scanning
I'm not sure if this is the most elegant way of doing it, but it's quite a simple solution and it does what I need.

Several template locations for Thymeleaf in Spring Boot

Currently Spring Boot allow one value for the Thymeleaf templates location with the spring.thymeleaf.prefix property.
The default value is classpath:/templates/.
I want to have another location for the thymeleaf templates (but keep the default one), outside the jar, for example:
spring.thymeleaf.prefix = classpath:/templates/, file:/resources/templates
Do i have to define another template resolver for the new location i want ?
Define the setting in the application.properties file
spring.thymeleaf.templateResolverOrder=1
Now in your custom Bean which creates ITemplateResolver set order to 0 along with prefix and suffix. This way spring boot will listen to both places
Setting order to 0 is important
An example of bean creation can be
#Bean
public ClassLoaderTemplateResolver emailTemplateResolver() {
ClassLoaderTemplateResolver emailTemplateResolver = new ClassLoaderTemplateResolver();
emailTemplateResolver.setPrefix("mails/");
emailTemplateResolver.setSuffix(".html");
emailTemplateResolver.setTemplateMode(TemplateMode.HTML);
emailTemplateResolver.setCharacterEncoding("UTF-8");
emailTemplateResolver.setOrder(0);
emailTemplateResolver.setCheckExistence(true);
return emailTemplateResolver;
}
MyExample
In order to define multiple template locations, you must define Spring beans implementing ITemplateResolver.
#Bean
public SpringResourceTemplateResolver firstTemplateResolver() {
SpringResourceTemplateResolver templateResolver = new SpringResourceTemplateResolver();
templateResolver.setPrefix("classpath:/templates/templatelocation/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setOrder(0);
templateResolver.setCheckExistence(true);
return templateResolver;
}
#Bean
public ClassLoaderTemplateResolver secondTemplateResolver() {
ClassLoaderTemplateResolver templateResolver = new ClassLoaderTemplateResolver();
templateResolver.setPrefix("templates/templatelocation/other/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode(TemplateMode.HTML);
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setOrder(1);
templateResolver.setCheckExistence(true);
return templateResolver;
}
You can also check out the blog post detailing the usage.

Spring and character encoding in properties files

I know, that there were many questions about the encoding in properties files, but I couldn't find answer which would help me, so I'm asking one more time.
So I have a Spring 4 based project with Java Config and with Thymeleaf as the templating engine.
I want to specify some labels in properties file, and read values of properties in the .html files using Thymeleaf's directive #{property.name}.
I already set up enconding in Character encoding Filter, I also set up encoding in messageSource (I'm using ReloadableResourceBundleMessageSource). I also added property to pom.xml:
UTF-8
And honestly, I'm out of ideas what I could do wrong.
What I didn't do from things which I have found in stackoverflow answers:
I didn't configured ant/maven native2ascii plugin, as I tried to change my characters (like ó or ł) to ascii counterparts, and almost all characters was still replaced by '??' signs.
I have also didn't configured maven-resource-plugin as I'm not sure why should I use it if all .properties files are available ?
EDIT
MessageSource definition:
#Bean(name = "messageSource")
public ReloadableResourceBundleMessageSource getMessageSource() {
ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
resource.setBasenames("/i18n/messages");
resource.setDefaultEncoding("UTF-8");
return resource;
}
WebApp initialization:
#Override
public void onStartup(ServletContext servletContext) throws ServletException {
WebApplicationContext context = getContext();
servletContext.addListener(new ContextLoaderListener(context));
ServletRegistration.Dynamic dispatcher = servletContext.addServlet("DispatcherServlet", new DispatcherServlet(context));
dispatcher.setLoadOnStartup(1);
dispatcher.addMapping("/");
FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter",
new CharacterEncodingFilter());
fr.setInitParameter("encoding", "UTF-8");
fr.setInitParameter("forceEncoding", "true");
fr.addMappingForUrlPatterns(null, true, "/*");
}
Maven properties definition
UTF-8
(other properties)
Reference in HTML file (in anchor tag):
th:href="#{about.html}" th:text="#{navigation.about}"
Properties files are: webapp/i18n/message_en_EN.properties, webapp/i18n/message_pl_PL.properties (both are saved in UTF-8 encoding by Intellij)
Ok so the problem was lying in Thymeleaf.
I was using ServletContextTemplateResolver and ThymeleafViewResolvere, and I had to set encoding in those two objects:
#Bean(name="templateResolver")
public ServletContextTemplateResolver getServletContextTemplateResolver() {
ServletContextTemplateResolver templateResolver = new ServletContextTemplateResolver();
templateResolver.setPrefix("/somepath/");
templateResolver.setSuffix(".html");
templateResolver.setTemplateMode("HTML5");
templateResolver.setCharacterEncoding("UTF-8");
templateResolver.setCacheable(false);
return templateResolver;
}
#Bean(name="viewResolver")
public ThymeleafViewResolver getThymeleafViewResolver() {
ThymeleafViewResolver viewResolver = new ThymeleafViewResolver();
viewResolver.setTemplateEngine(getTemplateEngine());
viewResolver.setOrder(1);
viewResolver.setCharacterEncoding("UTF-8");
return viewResolver;
}

Resources