Spring-boot ReloadableResourceBundleMessageSource not working - java

I have created a class TestReloadableResourceBundleMessageSource by extending ReloadableResourceBundleMessageSource in my application and implemented like this.
public class TestReloadableResourceBundleMessageSource extends ReloadableResourceBundleMessageSource {
//....
}
#Bean
public TestReloadableResourceBundleMessageSource messageSource() {
String messagesPath = "C:/messages";
TestReloadableResourceBundleMessageSource messageSource = new TestReloadableResourceBundleMessageSource();
messageSource.setBasename("file:" + messagesPath);
messageSource.setCacheSeconds(0);
messageSource.setDefaultEncoding(Charsets.UTF_8.name());
return messageSource;
}
But when I'm changing the properties file values, save and reload the page I'm getting the old values not new values without restarting the server.
My properties files are not in class path.
What could be reason and how can I reload it. Any solution will be appreciated.
I'm using spring-boot 1.4.4.RELEASE .

Below code is working for me.
#Bean
public ReloadableResourceBundleMessageSource messageSource() {
ReloadableResourceBundleMessageSource resource = new ReloadableResourceBundleMessageSource();
String messageFolderPath = propertyLocation + "/" + "i18n";
resource.setBasename("file:"+messageFolderPath+"/messages");
resource.setDefaultEncoding("UTF-8");
resource.setCacheSeconds(10);
return resource;
}

Related

Validation errors not picked up from resource file

I followed this link to implement a domain validation. However when I attempt to move the messages into a properties file, it doesn't work. I feel like it might be an issue with my validator implementation but can't quite figure out what is wrong. I followed a Baeldung article for this. The output doesn't get parsed and instead is displayed as "{modeltype.size.max}".
My domain object property looks like this:
#Column(name = "MODEL_TYPE")
#Size(max = 20, message = "{modeltype.size.max}")
private String modelType;
I also defined Beans for both the MessageSource & LocalValidatorFactoryBean like so:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocalValidatorFactoryBean getValidator() {
LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
bean.setValidationMessageSource(messageSource());
return bean;
}
My domain-specific validator method defined inside of the domain itself and called in the constructor:
private void validate(Equipment equipment) {
EntityValidator<Equipment> equipmentEntityValidator =
new AbstractEntityValidator<>(Validation
.buildDefaultValidatorFactory()
.getValidator());
Set<ConstraintViolation<Equipment>> failedValidations =
equipmentEntityValidator.validate(equipment);
List<String> failedValidationMessages = new ArrayList<>();
failedValidations.forEach(failedValidation -> failedValidationMessages.add(failedValidation.getMessage()));
if (!failedValidationMessages.isEmpty()) throw new ValidationException(String.join(",", failedValidationMessages));
}
This exception is then handled inside of the GlobalExceptionHandler and part of the response DTO are the constraint violations.

MessageSource doesn't reload properties file

There is a messageSource Bean:
#Bean
public MessageSource messageSource(){
ReloadableResourceBundleMessageSource messageSource=new ReloadableResourceBundleMessageSource();
messageSource.setDefaultEncoding("UTF-8");
messageSource.setBasenames("classpath:/messages/messages");
return messageSource;
}
I have read somewhere that If I use ReloadableResourceBundleMessageSource messageSource shouldn't be cached and everytime look into the properties file if theere is particular string. Sadly with bean created that way It doesn't work. After compiling If I add some properties Spring Boot won't find it.
Properties file is in /resources/messages/messages.properties and /resources/messages/messages_en.properties .
Try this solution.
First: configure the bean in your web configuration as shown below.
#Bean
public MessageSource messageSource () {
ReloadableResourceBundleMessageSourceExt messageResource =
new ReloadableResourceBundleMessageSourceExt();
messageResource.setAlwaysUseMessageFormat(false);
messageResource.setBasenames("classpath:messages");
messageResource.setDefaultEncoding(CHARACTER_ENCODING);
messageResource.setFallbackToSystemLocale(true);
messageResource.setUseCodeAsDefaultMessage(false);
messageResource.setCacheSeconds(1); // by default it set to -1 which means cache
// forever messageSourse.
// set 0 to check reload messeageSource on
// every getMessageSource request but reload
// only those files which last modified
// timestamp is changed.
// value greater than 1 is treated as the
// time interval between reload.
return messageResource;
}
Second: create a class which extends ReloadableResourceBundleMessageSource to expose the protected method of its inner class as shown below.
public class ReloadableResourceBundleMessageSourceExt extends ReloadableResourceBundleMessageSource {
public Properties getPropertiesByFileName(String fileName){
return super.getProperties(fileName).getProperties();
}
}
Third: Now Autowired the bean like this.
#Service
public class MyMessagesBundleService {
final private String fileName = "classpath:messages";
#Autowired
ReloadableResourceBundleMessageSourceExt messageSource;
Properties properties = messageSource.getPropertiesByFileName(this.fileName);
// now change the properties and saved it.
// after saved call clear cache and get again.
messageSource.clearCache();
}

spring get messagesource in java based configuration

I want to get messages loaded by messageSource bean, and want to use them in application context (java-based #Configuration class).
But I do not know how to.
I worked like below:
#Configuration
#ComponentScan(basePackages={
"com.musicovery12.study.service",
"com.musicovery12.study.dao"
})
public class ApplicationContext {
#Bean
public MessageSource messageSource(){
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:META-INF/application.properties");
messageSource.setUseCodeAsDefaultMessage(true);
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public DataSource dataSource(){
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(/*${db.driver-name}*/); // I want to set the parameter as given message stored by messageSource
return dataSource;
}
}
Any suggestion?
Thanks.
#Bean
public DataSource dataSource(){
String driverClassName = messageSource().getMessage(...);
BasicDataSource dataSource = new BasicDataSource();
dataSource.setDriverClassName(driverClassName); // I want to set the parameter as given message stored by messageSource
return dataSource;
}

How to inject MessageSource resource bundle with Spring?

Hi have two different message bundles. How can I directly inject them into a spring bean MessageSource?
The following does not work:
#Resource(name = "${messages_one_EB.properties}")
private MessageSource messageSourceOne;
#Resource(name = "${messages_two_EN.properties}")
private MessageSource messageSourceTwo;
Result: java.lang.IllegalArgumentException: Could not resolve placeholder 'messages_one_EB.properties'
Probably it works similar, but how? I could not find any example in the docs.
Both bundles are placed under src/main/resources/
I guess you can declare 2 different beans for your message sources and then inject them by name:
#Bean
public MessageSource messageSource1() {
final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:i18n/messages1");
messageSource.setFallbackToSystemLocale(false);
messageSource.setCacheSeconds(0);
return messageSource;
}
#Bean
public MessageSource messageSource2() {
final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:i18n/messages2");
messageSource.setFallbackToSystemLocale(false);
messageSource.setCacheSeconds(0);
return messageSource;
}
Then in your class:
#Resource(name = "messageSource1")
private MessageSource messageSourceOne;
#Resource(name = "messageSource2")
private MessageSource messageSourceTwo;

Spring MVC: No message found under code 'label.description' for locale 'en_us'

I'm trying to implement internationalisation on my project, however I cannot resolve my BaseName, so far this is my AppConfiguration class methods:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();`
messageSource.setBasename("messages/");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
#Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver resolver = new CookieLocaleResolver();
resolver.setDefaultLocale(new Locale("en_US"));
resolver.setCookieName("myLocaleCookie");
resolver.setCookieMaxAge(4800);
return resolver;
}
#Override
public void addInterceptors(InterceptorRegistry registry) {
LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
interceptor.setParamName("mylocale");
registry.addInterceptor(interceptor);
}
And this is my project structure:
Project Structure
Any ideas what I'm doing wrong? I also trying to change my baseName to classpath:messages but nothing. Thank you.
try this:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:/messages/messages");
messageSource.setDefaultEncoding("UTF-8");
return messageSource;
}
and rename your en_us.properties to messages_en_us.properties
just add this line to your application.properties
spring.messages.basename=validation

Categories

Resources