i18n works with Thymeleaf but not with MessageSource - spring

I am working with Spring MVC+Thymeleaf and getting the following exception when I tried to get a message from de the MessageSource: NoSuchMessageException
My configuration:
#Bean(name="messageSource")
public MessageSource messageSource(){
ReloadableResourceBundleMessageSource source = new ReloadableResourceBundleMessageSource();
source.setBasename("classpath:i18n/messages");
source.setUseCodeAsDefaultMessage(true);
source.setDefaultEncoding( propWebEncoding );
source.setCacheSeconds(0); /* check the last-modified timestamp */
return source;
}
My files are under:
src/main/resources/i18n/messages_es.properties
src/main/resources/i18n/messages_en.properties
My locale is “en”
When I use the message “myproperty.example” in HTML (Thymeleaf) it works fine but not when I try to get the message in my #Controller or #Service with:
#Autowired MessageSource messageSource;
And
messageSource.getMessage(“myproperty.example”, null, Locale.EN);
It raises NoSuchMessageException exception impossible to find … for locale ‘en’
This is all configured with maven and my i18n files are in the target folder under:
WEB-INF/classes/i18n/ [files]
What I am doing wrong?

The problem: I was working in two different contexts. I was calling MessageSource in the #Service tier (getRootConfigClasses) and it was configured in the ServletConfigClasses.
Solution: Only work in the root context (getRootConfigClasses)

Related

How to customize spring security messages in spring boot 2.3.1

I've defined this below bean as message source:
#Bean("messageSource")
public MessageSource messageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasenames("i18n/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
and this is content of messages.properties file under src/main/resources/i18n/ folder:
ExceptionTranslationFilter.insufficientAuthentication=A Custom message
AbstractAccessDecisionManager.accessDenied=A Custom message
Now, i expected to see A Custom message when an unauthorized user calls the rest, but get Full authentication is required to access this resource that is spring default exception message.
How can i solve this problem?

How to get values from message bundle?

In my application configuration class, I have the following entry:
#Bean(name = "messageSource")
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/i18n/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleResolver localeResolver(){
SessionLocaleResolver resolver = new SessionLocaleResolver();
resolver.setDefaultLocale(new Locale("pt_BR"));
return resolver;
}
The message_pt_BR.properties is located according to the attached image.
I'm trying to access an entry on this with a <span th:text="#{app.name}"></span> file and all I get is:
??app.name_pt_br??
What am I missing here?
Your message bundle name should be
messages_pt_BR.properties
It's case sensitive.
It's OK without default message bundle(messages.properties). Mine works fine with only _en and _zh_TW.
And it should be ok that you put your resource bundle everywhere if you give the correct path to set basename.
You need to replace your messages bundle to /resources folder.
Also you need to add messages.properties bundle, it's required.

Thymeleaf doesn't find message source

I'm actually confused about a part of my Thymeleaf configuration.
I have a property file located at classpath:/messages/web.properties. In my configuration the following is defined.
#Bean
public MessageSource messageSource() {
final ResourceBundleMessageSource messageSource;
messageSource = new ResourceBundleMessageSource();
messageSource.setDefaultEncoding("UTF-8");
messageSource.setBasename("messages/web");
return messageSource;
}
If I run my application with this configuration everything works fine. The messages from the properties file are injected into the Thymeleaf template (as expected).
But if I change the name of the method which creates my message source, restart my application and request the same page... then the messages from my web.properties file are not found.
#Bean
public MessageSource webMessageSource() {
[...]
}
Why the bean name (= method name) of the message resource has this impact to my application?
Why the message source webMessageSource could not be found by the Thymeleaf template engine?
After a little digging around in the Thymeleaf source code, I found that in the class SpringTemplateEngine the Javadoc clearly states:
It also configures a {#link SpringMessageResolver} as message
resolver, and implements the {#link MessageSourceAware} interface in
order to let Spring automatically setting the {#link MessageSource}
used at the application (bean needs to have id
"messageSource"). If this Spring standard setting needs to be
overridden, the {#link #setTemplateEngineMessageSource(MessageSource)}
can be used.
The important part is bean needs to have id "messageSource"
As noted by #ShinichiKai, this part of the Spring documentation mentions that the name of the MessageSource bean in Spring must be messageSource.

Why messages don't show up?

I have message property files in my Spring web application. The following is a related configuration:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasenames("classpath:messages");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
messageSource.setCacheSeconds(0);
return messageSource;
}
The message in the property doesn't show up but the key with a language suffix. For example, a key, nav.welcome, in the property file is shown on a web page as ??nav.welcome_en?? I use Gradlew to run my application. And I see the messages.properties file on the root of the class path.
C:\Users\vic\workspace-sts\myapp\build\tmp\tomcatRunWar\work\Tomcat\localhost\_\WEB-INF\classes>
After turning up org.springframework.web log level, I see the following related log messages:
DEBUG: AnnotationConfigWebApplicationContext:649 - Unable to locate MessageSource with name 'messageSource': using default [org.springframework.context.support.DelegatingMessageSource#2a83e48a]
and
DEBUG: AnnotationConfigWebApplicationContext:639 - Using MessageSource [org.springframework.context.support.ResourceBundleMessageSource: basenames=[classpath:messages]]
What is missing here?

How to get properties in JSP files using spring mvc 3

I am very new to spring mvc 3 annotation based application. I have two properties files -
WEB-INF\resources\general.properties,
WEB-INF\resources\jdbc_config.properties
Now I want to configure them through spring-servlet.xml. How I can achieve this?
In general.properties,
label.username = User Name:
label.password = Password:
label.address = Address:
...etc
jdbc_config.properties,
app.jdbc.driverClassName=com.mysql.jdbc.Driver
app.jdbc.url=jdbc:mysql://localhost:[port_number]/
app.jdbc.username=root
app.jdbc.password=pass
---etc
If I want to get label.username and app.jdbc.driverClassName in my jsp page, how do I code for them?
I also want to access these properties values from my service. How to get these property values using respective keys in method level in service class or controller class?
You need to distinguish between application properties (configuration) and localisation messages. Both use JAVA properties files, but they serve different purpose and are handled differently.
Note: I am using Java based Spring configuration in the examples bellow. The configuration can be easily made in XML as well. Just check Spring's JavaDoc and reference documentation.
Application Properties
Application properties should be loaded as property sources within your application context. This can be done via #PropertySource annotation on your #Configuration class:
#Configuration
#PropertySource("classpath:default-config.properties")
public class MyConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertyPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Then you can inject properties using #Value annotation:
#Value("${my.config.property}")
private String myProperty;
Localisation Messages
Localisation messages is a little bit different story. Messages are loaded as resource bundles and a special resolution process is in place for getting correct translation message for a specified locale.
In Spring, these messages are handled by MessageSources. You can define your own for example via ReloadableResourceBundleMessageSource:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("/WEB-INF/messages/messages");
return messageSource;
}
You can access these messages from beans if you let Spring inject MessageSource:
#Autowired
private MessageSource messageSource;
public void myMethod() {
messageSource.getMessage("my.translation.code", null, LocaleContextHolder.getLocale());
}
And you can translate messages in your JSPs by using <spring:message> tag:
<spring:message code="my.translation.code" />
I ended up using Environment
Add these lines to config
#PropertySource("classpath:/configs/env.properties")
public class WebConfig extends WebMvcConfigurerAdapter{...}
You can get the properties from controller using autowired Environment
public class BaseController {
protected final Logger LOG = LoggerFactory.getLogger(this.getClass());
#Autowired
public Environment env;
#RequestMapping("/")
public String rootPage(ModelAndView modelAndView, HttpServletRequest request, HttpServletResponse response) {
LOG.debug(env.getProperty("download.path"));
return "main";
}
}
Firstly import spring tag lib:
<%# taglib prefix="security" uri="http://www.springframework.org/security/tags" %>
Than import property from your application.properties
<spring:eval var="registration_url" expression="#environment.getProperty('service.registration.url')"/>
Than use your variable
test

Resources