Spring ReloadableResourceBundleMessageSource bean unable to find external properties - spring

I've tried to use the Mkyong's guide to access external properties file, without any success.
This is my bean definition in web-osgi-context.xml file located in WEB-INF:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:bundles/resource</value>
<value>classpath:bundles/override</value>
<value>file:c:/test/messages</value>
</list>
</property>
<property name="cacheSeconds" value="10"/>
</bean>
Accessing the bean:
#SpringBean
private ReloadableResourceBundleMessageSource messageSource;
Trying to extract the message like this:
String name = messageSource.getMessage("customer.name",
new Object[] { 28,"http://www.mkyong.com" }, Locale.US);
System.out.println("Customer name (English) : " + name);
I have messages_en_US.properties files in both C:/test/messages and C:/test folders. They contain following line:
customer.name=Test, age : {0}, URL : {1}
That's all I have, am I missing something? The message I get is:
org.springframework.context.NoSuchMessageException: No message found under code 'customer.name' for locale 'en_US'.
at org.springframework.context.support.AbstractMessageSource.getMessage(AbstractMessageSource.java:155)
Btw, I also tried internal properties, also without success. I deploy my .war in my local servicemix(6.1.1), I also use wicket (6.24.0) and spring (3.2.14). Running mkyong's application(which is not a web application) locally (without deploying it on my local servicemix works).

Sooo I somewhat found the problem and got a workaroud..
This didn't work:
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basename">
<value>classpath:messages</value>
</property>
</bean>
And in Code:
#SpringBean
private ReloadableResourceBundleMessageSource messageSource;
By running getClass() on this source I get
class WICKET_org.springframework.context.support.ReloadableResourceBundleMessageSource$$EnhancerByCGLIB$$852b0c02
But this is working:
#Bean
public MessageSource messageSource() {
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
return messageSource;
}
By running getClass() on this source I get
class org.springframework.context.support.ReloadableResourceBundleMessageSource
Is it possible that Cglib enhancer is messing thigs up here? Any way I can make first option working knowing that?

Related

Convert application context to Java Config Springboot

Looking for some guidance on converting below in existing applicationContext.xml into Java Config for a new Springboot application.
<bean id="InitialHandler" class="package.InitialHandler"
scope="prototype">
<property name="rawResponseTemplate"
ref="rawResponseRestTemplate"/>
<property name="mimeMapper" ref="initialMimeMapper"/>
</bean>
<bean id="rawResponseRestTemplate"
class="org.springframework.web.client.RestTemplate">
<property name="messageConverters">
<list>
<bean class="package.CommonDocumentRawMessageConverter"/>
</list>
</property>
</bean>
<bean id="initialMimeMapper"
class="package.ConfigurationBasedMapper">
<property name="configuration" ref="initialMimeConfig"/>
</bean>
<bean id="initialMimeConfig"
class="org.apache.commons.configuration.XMLPropertiesConfiguration"
scope="singleton">
<constructor-arg type="java.net.URL"
value="classpath:FileINeedLoaded.xml"/>
<property name="reloadingStrategy" ref="ReloadingStrategy"/>
</bean>
// snippet of CommonDocumentRawMessageConverter below
import org.springframework.http.converter.HttpMessageConverter;
public class CommonDocumentRawMessageConverter implements
HttpMessageConverter<CommonDocument> {}
This is what i have:
#Bean
public RestTemplate rawResponseRestTemplate() {
RestTemplate rawResponseRestTemplate = new RestTemplate();
rawResponseRestTemplate.setMessageConverters(msgConverters());
return rawResponseRestTemplate;
}
private List<HttpMessageConverter<?>> msgConverters() {
List<HttpMessageConverter<?>> newList = new ArrayList<HttpMessageConverter<?>>();
newList.add(new CommonDocumentRawMessageConverter());
return newList;
}
Service compiles OK but get runtime exception as follows:
***************************
APPLICATION FAILED TO START
***************************
Description:
Failed to bind properties under 'prop.mime-mapper' to
package.util.Mapper<java.lang.String>:
Property: prop.mime-mapper
Value: propMimeMapper
Origin: "prop.mimeMapper" from property source "Config resource 'class
path resource [application.yml]' via location 'optional:classpath:/'
(document #0)"
Reason: org.springframework.core.convert.ConverterNotFoundException: No
converter found capable of converting from type [java.lang.String] to
type [package.util.Mapper<java.lang.String>]
Action:
Update your application's configuration
Snippet of my config:
#Getter
#Setter
public class propConfig {
private String randomProp;
private Mapper<String> mimeMapper;
private RestTemplate rawResponseTemplate;
Service:
#Slf4j
#Service
public class PropService extends DocumentManagementService {
private final RestTemplate rawResponseTemplate;
private final Mapper<String> mimeMapper;
public PropService(#Autowired PropConfig propConfig) {
this.rawResponseTemplate = propConfig.getRawResponseTemplate();
this.mimeMapper = propConfig.getMimeMapper();
}
It appears that at runtime the properties defined as RestTemplate and Mapper are not getting converted for some reason.
UPDATE ONE
I was able to fix above issue by removing these properties from the application.yaml altogether.
private Mapper<String> mimeMapper;
private RestTemplate rawResponseTemplate;
I realised that these properties were actually 'refs' in the original applicationContext.xml and thus not required in the new application.yaml. I do have new issues however related to this conversion which i will share. I will keep original configs in place in case others have same issue.
I was able to fix above issue by removing these properties from the application.yaml altogether.
private Mapper<String> mimeMapper;
private RestTemplate rawResponseTemplate;
I realised that these properties were actually 'refs' in the original applicationContext.xml and thus not required in the new application.yaml.

Converting bean from spring to spring boot

My problem statement is as follows :
I want to connect to db and from a table get certain values and assign those to a bean. In current spring project, it is done as follows :
The class com.some.DbPropertyPlaceholderConfigurer is in a jar file.
<bean id="propertyConfigurer"
class="com.some.DbPropertyPlaceholderConfigurer">
<property name="dataSourceName" value="dataSource" />
<property name="locations">
<list>
<value>classpath:resources/context.properties</value>
</list>
</property>
</bean>
<bean id="someObject" class="com.some.beans.SomeObject">
<property name="someprop" value="${prefix.someprop}" />
<property name="someprop1" value="${prefix.someprop1}" />
<property name="someprop2" value="${prefix.someprop2}" />
....
</bean>
DbPropertyPlaceholderConfigurer is in a jar file, it reads from a db table.
The Db table has key value columns.
The key contains "prefix.someprop" and it has some value.
Now, I am working on converting spring beans into spring boot beans using annotations.
Following is the bean in spring.
I came up with following for spring boot but bean it is not getting initialized.
I am not sure how to map properties "dataSourceName" and "locations"
#Configuration
public class AppConfig {
#Bean
public DbPropertyPlaceholderConfigurer propertyConfigurer() {
return new DbPropertyPlaceholderConfigurer();
}
#Bean
public SomeObject someObject() {
return new SomeObject();
}
}
It throws following exception :
[localhost-startStop-1] ERROR org.springframework.boot.SpringApplication - Application run failed
org.springframework.beans.factory.BeanInitializationException: Could not load properties; nested exception is java.lang.NullPointerException
at com.some.configuration.DbPropertyPlaceholderConfigurer.processProperties(DbPropertyPlaceholderConfigurer.java:130)
Also if it gets initialzed, how will I actually use it ?

Load configuration files dynamically using Spring

We already have a setup in which we are loading files like :
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:${AN_ENV_CONFIGURED_DIR}/project.properties</value>
</list>
</property>
The config files are there in server in a separate location. I want to load the configuration files dynamically if there is a change in it. Now since I already have this setup is there a simple way to reload config files from Spring other than using TimerTask and if its the only way then still its not sufficing the need to loading the file immediately.
You can use ReloadableResourceBundleMessageSource, following is the code snippet.
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>file:${AN_ENV_CONFIGURED_DIR}/project.properties</value>
</list>
</property>
<property name="cacheSeconds" value="1"/>
</bean>
For more info : http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/context/support/ReloadableResourceBundleMessageSource.html
Use the below bean to reload config.properties every 1 second.
#Component
public class PropertyLoader {
#Autowired
private StandardEnvironment environment;
#Scheduled(fixedRate=1000)
public void reload() throws IOException {
MutablePropertySources propertySources = environment.getPropertySources();
PropertySource<?> resourcePropertySource = propertySources.get("class path resource [config.properties]");
Properties properties = new Properties();
InputStream inputStream = getClass().getResourceAsStream("/config.properties");
properties.load(inputStream);
inputStream.close();
propertySources.replace("class path resource [config.properties]", new PropertiesPropertySource("class path resource [config.properties]", properties));
}
}
Your main config will look something like:
#EnableScheduling
#PropertySource("classpath:/config.properties")
public class HelloWorldConfig {
}
Then access the property any where:
#Autowired
private Environment environment;
environment.get("my.property");

Reading message from properties file in spring4

I am facing an issue in reading the properties file in spring mvc4. To read messages I have added following in spring-servlet.xml file located under WEB-INF folder.
<context:component-scan base-package="com.test.restful.producer" />
<bean class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="location">
<value>classpath:application.properties</value>
</property>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
In my controller class,
#Value("${MSG}")
private String msg;
i am getting msg as null. Please helpout me how to load properties file. My appilcation.properties file is available in classpath only.
I am using Spring-4.0.5
Thank you
You can try this xml for creating properties bean.
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:propertyFile.properties" name="propertiesBean"/>
Or go for non xml version as below
#PropertySource("classpath:propertyFile.properties")
public class AppConfig {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}

How to configure messages.properties in spring bean annotation?

I am starting a new project with spring 4 and I am confusing how I can map my i18n file: messages.properties..
In spring 3 I was using xml configuration like this:
<bean id="localeResolver" class="org.springframework.web.servlet.i18n.CookieLocaleResolver" />
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="messages" />
</bean>
<bean id="i18n" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:/..../messages.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
And in my jsps files I access it by:
<spring:message code="any key" />
In spring 4 I am avoiding to use xml configuration.. I tried the following:
#Bean
public ResourceBundleMessageSource messageSource() throws Exception {
ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
resourceBundleMessageSource.setBasename("message.properties");
return resourceBundleMessageSource;
}
#Bean
public PropertiesFactoryBean propertiesFactoryBean() throws Exception {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
Resource resource = new ClassPathResource("messages.properties");
propertiesFactoryBean.setLocation(resource);
return propertiesFactoryBean;
}
That class is annotated with #Configuration, but apparently is missing anything..
When I try to access index.jsp, I receive the following exception:
org.apache.jasper.JasperException: javax.servlet.ServletException: javax.servlet.jsp.JspTagException: No message found under code 'application.title' for locale 'pt_BR'.
Any help is appreciated.
Thanks
try
<spring:message code="myMessage"/> with <fmt:message key="myMessage"/>
and on web.xml
<context-param>
<param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
<param-value>messages</param-value>
</context-param>
dont forget to add fmt taglib
You need to put file name for each local language. In your case you need
messages_BR.properties or messages_pt_BR.properties
And all the messages in those files.

Resources