Reading message from properties file in spring4 - spring

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();
}

Related

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");

Spring ReloadableResourceBundleMessageSource bean unable to find external properties

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?

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.

How to log properties loaded by Spring?

is it possible to simply log all the content of the properties file loaded by spring with <context:property-placeholder /> ?
Thanks
You can set the log level of org.springframework.core.env.PropertySourcesPropertyResolver to "debug". Then, you will be able to see the value of the properties during resolving.
You can do it this way:
<context:property-placeholder properties-ref="myProperties"/>
<bean id="myProperties"
class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
.. locations
</list>
</property>
</bean>
and add a logging bean similar to one below (here annotation based and with slf4j api):
#Component
public class PropertiesLogger {
private static Logger logger = LoggerFactory.getLogger(PropertiesLogger.class);
#Resource("myProperties")
private Properties props;
#PostConstruct
public void init() {
for (Map.Entry<Object, Object> prop : props.entrySet()) {
logger.debug("{}={}", prop.getKey(), prop.getValue());
}
}
}

How to inject complete propertiesfile in a springbean

I have a properties-file with a lot of values and I do not want to list them in my bean-configuration-file separately. E.g.:
<property name="foo">
<value>${foo}</value>
</property>
<property name="bar">
<value>${bar}</value>
</property>
and so on.
I imagine to inject all completely as java.util.Properties or less as a java.util.Map.
Is there a way to do so?
For Java config you can use something like this:
#Autowired #Qualifier("myProperties")
private Properties myProps;
#Bean(name="myProperties")
public Properties getMyProperties() throws IOException {
return PropertiesLoaderUtils.loadProperties(
new ClassPathResource("/myProperties.properties"));
}
You can also have multiple properties this way, if you assign a unique bean name (Qualifier) to each instance.
Yes, you can use <util:properties> to load a properties file and declare the resulting java.util.Properties object as a bean. You can then inject that as you would any other bean property.
See section C.2.2.3 of the Spring manual, and their example:
<util:properties id="myProps" location="classpath:com/foo/jdbc-production.properties"
Remember to declare the util: namespace as per these instructions.
For Java Config, use PropertiesFactoryBean:
#Bean
public Properties myProperties() {
PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
propertiesFactoryBean.setLocation(new ClassPathResource("/myProperties.properties"));
Properties properties = null;
try {
propertiesFactoryBean.afterPropertiesSet();
properties = propertiesFactoryBean.getObject();
} catch (IOException e) {
log.warn("Cannot load properties file.");
}
return properties;
}
And then, set the properties object:
#Bean
public AnotherBean myBean() {
AnotherBean myBean = new AnotherBean();
...
myBean.setProperties(myProperties());
...
}
Hope this helps for those interested in Java Config way.
It's possible with the PropertyOverrideConfigurer mechanism:
<context:property-override location="classpath:override.properties"/>
Properties file:
beanname1.foo=foovalue
beanname2.bar.baz=bazvalue
The mechanism is explained in the section 3.8.2.2 Example: the PropertyOverrideConfigurer
This is an echo of #skaffman's response in this SO question. I am adding more details to help others and myself when I try to solve this in the future.
There are three ways to inject the property file
Method 1
<bean id="myProps" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>classpath:com/foo/jdbc-production.properties</value>
</list>
</property>
</bean>
Reference ( link )
Method 2
<?xml version="1.0" encoding="UTF-8"?>
<beans
...
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="...
...
http://www.springframework.org/schema/util/spring-util.xsd"/>
<util:properties id="myProps" location="classpath:com/foo/jdbc-production.properties"/>
Reference ( link )
Method 3
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:com/foo/jdbc-production.properties" />
</bean>
Reference ( link )
Essentially, all the methods can create a Properties bean out of the properties file. You may even directly inject a value from the property file by using #Value injector
#Value("#{myProps[myPropName]}")
private String myField;

Resources