External properties file as spring MessageSource not working - java

Consider below code:
<bean id="busmessageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>classpath:bundles/resource</value>
<value>classpath:bundles/override</value>
<value>file:/C:/mmt/override</value>
</list>
</property>
<property name="cacheSeconds" value="100" />
</bean>
Here properties from bundles/resource and bundles/override get fetched when I call busmessageSource.getMessage("anykey", null, null)
but it fails when I try to fetch values for properties in C:/mmt/override
What is correct way of configuring messagesource with external file from the disk.
Also I want file:/C:/mmt/override to override values in classpath:bundles/override if any with the same key exist. How do I override properties from an external file outside of my war folder?

1.) I have these 3 ways:
One solution is to add your "C:/mmt/" folder to your resource classpath.
This is another way that may help you ResourceBundle not found for MessageSource when placed inside a folder
Use this code: (Worked for me)
<beans:bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<beans:property name="basename">
<beans:value>file:/path/to/messages</beans:value>
</beans:property>
</beans:bean>
Note1: You must use the } file: prefix and the ReloadableResourceBundleMessageSource class.
Note2: Do not put the ".properties" extension.
2.) You override previous values when you load a new properties file with same property names (keys). You must ensure that you fetch last the properties file you want to use.

You can try
<bean id="messageSource"
class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="defaultEncoding" value="UTF-8"/>
<property name="basenames">
<list>
<value>classpath:bundles/resource</value>
<value>classpath:bundles/override</value>
<value>file:C:/mmt/override</value>
</list>
</property>
</bean>
About message resource keep note:
A plain path will be relative to the current application context.
A "classpath:" URL will be treated as classpath resource.
A "file:" URL will load from an absolute file system path.
Any other URL, such as "http:", is possible too.

I ran into similar question (by the title of your question) and managed to instantiate Spring ResourceBundleMessageSource with java.util.Properties.
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setCommonMessages(properties);
Kind of naive approach, but did the job for my unit testing.

Related

Not able to find messages with ResourceBundleMessageSource

I am currently using the following code which is working correctly:
<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
<property name="basenames">
<list>
<value>/WEB-INF/resources/lang/lang</value>
</list>
</property>
<property name="defaultEncoding" value="UTF-8"/>
</bean>
When I change ReloadableResourceBundleMessageSource to just ResourceBundleMessageSource it stops working.
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="/WEB-INF/resources/lang/lang" />
</bean>
I keep getting exceptions saying "No message found under code 'title' for locale 'en_US'." (title is an example)
After reading similar questions, I have also tried changing the value of basename parameter to any of the following, without success:
WEB-INF/resources/lang/lang
.WEB-INF.resources.lang.lang
WEB-INF.resources.lang.lang
resources.lang.lang
lang.lang
lang
classpath:resources.lang.lang
Making a file called lang_en_US.properties didn't help either.
Apparently, it is looking in the java folder (root of classpath) and not the web folder.
I created a new package called lang in the java folder and moved the lang*.properties files to it.
Then I put lang.lang as the value for basename and it started to work.
UPDATE: This stopped working after a project clean. The lang files should go into the "resources" folder, not the java folder. They technically end up in the same place after a build, but the IDE seems to ignore non-class files in the java folder and simply skips them.

Spring ResourceBundle not found for base name

I'm having problems taking the message values to a properties file.
I'm using intelliJ IDEA and i have a package
com.test.messages
and inside I have the messages.properties file.
Here is my xml
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="com.test.messages.messages"/>
</bean>
When I restart the server this is the WARNING i get
WARNING: ResourceBundle [com.test.messages.messages] not found for MessageSource: Can't find bundle for base name com.test.messages.messages, locale en_US
Any ideas?
Do not keep properties in packages.
Resources directory is a standart place to keep internal properties.
/src/main/resources
or
/src/test/resources
If you want to keep properties separated from the project - use something this kind of spring configuration:
<bean id="props" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" >
<property name="ignoreResourceNotFound" value="true"/>
<property name="localOverride" value="true"/>
<property name="locations">
<list>
<value>classpath*:messages.properties</value>
<value>file:messages.properties</value>
</list>
</property>
</bean>
So you'd be able to override internal properties with external (don't forget to add the to a classpath using -cp).
Anyway the declaration of the been will look like this:
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basename" value="${property.name}"/>
</bean>
you should have a file in your project as such:
src\main\resources\com\test\messages.properties
Although I am not IDEA expert, I know that resources such as .property files placed in the source code hierarchy are copied to the classpath when using the IDE alone. However, if you use maven, then it takes over the build and whatever is in the java path is not copied by default. You have to place all your classpath resources in src\main\resources and under whatever hierarchy mirrors the package name to have the same result. So in your case :
src\main\resources\com\test\messages\messages.properties
and maven will copy it properly
I know this is old question, but let me drop my solution :)
Source folder (resources is not package):
/src/main/java/
somepackage/abc.java
/src/main/resources/
messages.properties
Eclipse default output java build path:
myProject/build/classes
Eclipse default deploy path:
WEB-INF/classes
My project's spring context XML file path:
/src/main/webapp/WEB-INF/context.xml
Inject resource bundles,
<bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="messages"/>
</bean>
As Azee said keeping properties in package is not encourage. In case, messages.properties is in resources package as below:
/src/resources/messages.properties
context.xml should be like:
<property name="basenames" value="resources/messages"/>

How to read jBoss configuration files in Spring?

I want to have a project independent configuration file that I can access from different projects. What I'm currently trying (and does not give me good results at all):
<bean id="wroProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="${JBOSS_HOME}/standalone/configuration/wro.properties" />
</bean>
I use Spring 3 and JBoss 7.1. My configuration files are under jboss/standalone/configuration/....properties. Besides that I want to read message files from that same directory with:
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="messages,local" />
<property name="useCodeAsDefaultMessage" value="true" />
</bean>
Currently it looks for messages.properties and local.properties in src folder?
This is the solution I ended up using, which is platform independent and portable:
<bean id="wroProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" value="file:#{systemProperties['jboss.home.dir']}/standalone/configuration/wro.properties" />
</bean>
The configuration of the message source is identical.
A ResourceBundleMessageSource uses the basenames provided to (and the locale) to build a resource name (ex. message.properties) which is eventually (in the call stack) used by java.util.ResourceBundle.Control#newBundle(...). This resource name is then looked for on the classpath starting at its root (ex. /message.properties).
If you're on an IDE like Eclipse, your classpath very likely starts at src.
If jboss/standalone/configuration/... is on your classpath as well and the properties file are in there, you can change the basenames to
<bean id="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<property name="basenames" value="jboss/standalone/configuration/messages,jboss/standalone/configuration/local" />
<property name="useCodeAsDefaultMessage" value="true" />
</bean>

Specifying Locations relative to the context XML in Spring

Is there a way to reference a properties file on a file system (not on a classpath) relative to the Spring's context file itself?
What I want to do is the below:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<!-- I want the below to be relative to this context XML file. -->
<value>app.properties</value>
</list>
</property>
</bean>
I was imagining something like ${contextpath} that I could prepend to the above "app.properties" but couldn't find anything helpful.
Thanks.
You can reference properties on the classpath via the classpath: prefix:
<value>classpath:app.properties</value>

Can I use an Environment variable based location for Spring FileSystemResource?

I have a requirement to have all our properties files be stored in a directory. The location of this directory should be stored in a system environment variable. In my application context I will need to access this environment variable to create the FileSystemResource bean. Here is an example of what I would normally have:
<bean id="properties" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<bean class="org.springframework.core.io.FileSystemResource">
<constructor-arg>
<value>myprops.properties</value>
</constructor-arg>
</bean>
</property>
</bean>
Instead I will need to have it be something like
<value>${prop_file_location}/myprops.properties</value>
Where prop file location is an environment variable. Does anyone know an easy way of doing this?
I am using spring 2.5.6 and java 1.6
UPDATE
We later upgraded to Spring 3.0.X and we were able to take advantage of the spring expression language. Our approach simplified from three beans to the following snippet:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:defaults.properties</value>
<value>file:/a/defined/location/project.properties</value>
<value>file:${AN_ENV_CONFIGURED_DIR}/project.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
<property name="searchSystemEnvironment" value="true" />
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>
This allowed us to have either a development (the first defaults) statically well known location, or a deployed location configured via env variables. The configurer processes these in order (i.e. the deployed takes precedence over the defaults).
OLD
I ended up going with a non programmatic approach. I used a MethodInvoker to retrieve the environment value. I was able to then pass that into the FileSystemResource.
<bean id="configPath" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean" >
<property name="targetClass" value="java.lang.String" />
<property name="staticMethod" value="java.lang.System.getenv" />
<property name="arguments">
<list>
<value>NAME_OF_VARIABLE</value>
</list>
</property>
</bean>
while I note that the question required 2.5.x, it's worth pointing out that Spring 3's EL support (available since Nov 2009) would've made short work of this sort of thing
#Value("#{ systemProperties['user.home'] }")
private String userHome ;
or
<property name = "userHome" value ="#{ systemProperties['user.home'] }"/>
You could always extend the FileSystemResource (i.e. PropertiesFileResource) that would initialize itself by taking prepending the property file location system property to the file path.
In Spring.Net we have got the IVariableSource interface and PropertyPlaceholderConfigurer which are able to retrieve values from environment variables. Maybe there is something similar in the Spring Framework for Java?
Edit: I think I found the corresponding java bean which is named PropertyPlaceholderConfigurer as well in the java docs.
Example:
Start you app with -DDA_HOME=c:\temp
c:\temp must contain directory called "config"
In c:\temp\config you have file app.properties (for example)
Extend the Spring loader:
public class Loader extends org.springframework.beans.factory.config.PropertyPlaceholderConfigurer{
private String appHome;
public void setAppHome(String appHome) {
this.appHome = appHome;
}
#Override
public void setLocation(Resource location) {
if(appHome==null){
throw new RuntimeException("You must specify VM property DA_HOME, this directory must contain " +
"another directory, called config, inside the config directory app.properties " +
"file must be found with the configuration properties");
}
String configurationDirectory = appHome + System.getProperty("file.separator") + "config";
String fileName = location.getFilename();
Resource file = new FileSystemResource( configurationDirectory + System.getProperty("file.separator")+ fileName);
super.setLocation(file);
}
}
Specify the new loader and its configuration base:
<bean id="placeholderConfig" class="your.Loader">
<property name="appHome" value="#{systemProperties['DA_HOME']}"/>
<property name="location" value="app.properties" />
</bean>

Categories