How to load system properties in Spring for properties file location - java

I am working on a Spring application where the properties file will be packaged inside the the .war file for deployment.
<context:property-placeholder location="classpath:application.properties" />
However, I would like to be able to override them with another file that can be specified in standalone.xml as a system property:
</extensions>
<system-properties>
<property name="CONFIG_FILE_LOCATION" value="/path/to/application.properties"/>
</system-properties>
This was my solution,
<context:property-placeholder location="classpath:application.properties,
file:///${CONFIG_FILE_LOCATION}" />
but apparently Spring is unable to find it
Caused by: java.io.FileNotFoundException: ${CONFIG_FILE_LOCATION} (The system cannot find the file specified)
Does anyone has any idea how I might fix it? Is there another way Spring accesses the system properties?

It is actually possible in Spring to override certain properties by specifying a system property location to another file using this solution:
<context:property-placeholder location="classpath:alarm_notification.properties, file:///${CONFIG_FILE_LOCATION}" />
If a certain property is not overridden inside the file located at CONFIG_FILE_LOCATION, the value from application.properties will be used instead.
Just make sure to have the following configuration in the standalone.bat file used to start the server:
</extensions>
<system-properties>
<property name="CONFIG_FILE_LOCATION" value="/path/to/application.properties"/>
</system-properties>

You need to file namespace for that as follows:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:/myFolder/folder/path/application.properites</value>
</list>
</property>
or as follows:
<context:property-placeholder locations="file:/myFolder/folder/path/application.properites"/>

Related

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 use environment variables with properties file in Spring context file

I am trying to read in a configuration file based on a system environment variable. My environment variable is FOO_ENV with value dev and dev.properties contains the properties bar.host and bar.port.
<context:property-placeholder />
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:${FOO_ENV}.properties"></property>
<property name="ignoreUnresolvablePlaceholders" value="true" />
</bean>
<bean id="myServer" class="org.apache.solr.client.solrj.impl.HttpSolrServer">
<property name="ignoreUnresolvablePlaceholders" value="true" />
<constructor-arg type="String" value="http://${my.host}:${my.port}/" />
</bean>
When I deploy this in tomcat, I get the following error:
11:48:39.324 [localhost-startStop-14] ERROR o.s.web.context.ContextLoader - Context initialization failed
org.springframework.beans.factory.BeanDefinitionStoreException: Invalid bean definition with name 'myServer' defined in ServletContext resource [/WEB-INF/my-context.xml]:
Could not resolve placeholder 'my.host' in string value [http://${my.host}:${my.port}]
at org.springframework.beans.factory.config.PlaceholderConfigurerSupport.doProcessProperties(PlaceholderConfigurerSupport.java:209) ~[spring-beans-3.1.2.RELEASE.jar:3.1.2.RELEASE]
By replacing $FOO_ENV with dev in the context file, I have determined that the properties file can be read correctly. By changing FOO_ENV to other names, I can show that Spring is reading the environment variable.
It seems that the element
<property name="ignoreUnresolvablePlaceholders" value="true" />
should allow Spring to ignore that ${my.host} is not an environment variable, but though I've tried it in various places, I still get the same error, which indicates that my.host is not found.
You actually have two PropertyPlaceHolderConfigurers defined here. One via the context namespace and one explicitly. Spring is probably picking the one created via the context namespace. You could either set 'ignore-unresolvable' on the context tag and remove your propertyConfigurer bean like so:
<context:property-placeholder ignore-unresolvable="true"/>
Or if you need more control over PropertyPlaceHolderConfigurer go the other way and remove the context:property-placeholder tag.

How to load data from property file into bean property values?

I am following the following article.
http://www.mkyong.com/spring/spring-quartz-scheduler-example/
Everything works fine.
<bean id="simpleTrigger"
class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<property name="jobDetail" ref="runMeJob" />
<property name="repeatInterval" value="5000" />
<property name="startDelay" value="1000" />
</bean>
I created a property file app.properties which has
repeatInterval = 5000
startDelay = 1000
I want to load these data into bean properties. Right now I have to hard code the values into the xml file.
I want to be able to load the data from property file into the bean properties. Is it possible?
EDIT:
I have
<property name="repeatInterval" value="5000" />
What I am looking for is a way to make it
<property name="repeatInterval" value= "get 5000 from property file" />
To find a file myPropertyFileName.properties that is on your classpath and load it into your spring config, create the following bean:
<bean id="myPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:myPropertyFileName.properties"/>
<property name="placeholderPrefix" value="${props:"/>
</bean>
Then use a property name defined like
repeatInterval=5000
like this:
<property name="repeatInterval" value="${props:repeatInterval}"/>
Use Spring propertyPlaceholderConfigurer to achieve this. Follow this guide.
I have run into something similar in the past. I needed to load a bunch of beans using Spring but I wanted them to be user editable bean files. So I didn't want to include them in the jar packaging. What I did was create my user-defined bean files outside the jar but in a know relative location. My packaged bean definition file referenced the beans defined in the user-defined bean file and when I loaded the application context I provided both files (user-defined & packaged).
Bit unorthodox but it worked.

Controlling log file location via JNDI in Spring?

I have a Java web application that uses the SLF4J logging facade. To date, we use the Log4J implementation underneath (though we are considering a switch to Logback). Log4J is currently configured via a log4j.xml configuration file that is placed in the root of our classpath.
In any event, we use JNDI to configure other aspects of our application so I am very familiar with how to set that up and pull a string from JNDI into a Spring configuration file.
However, I am at a loss to figure out how to create a Log4J appender from within a Spring configuration file. Better yet, can one completely configure Log4J via Spring and skip the log4j.xml configuration file altogether? I am hoping I don't have to do this programmatically.
I found a Spring class called Log4jWebConfigurer but this requires that the WAR run exploded (don't want that if I can help it) and also that the log file resides within the web-app directory (definitely don't want that).
First get the main directory via JNDI:
<jee:jndi-lookup id="myAppHome" jndi-name="myAppHome" />
Then use that bean in a Spring Expression Language statement in the the following way:
<bean id="log4jInitialization" class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<property name="targetClass" value="org.springframework.util.Log4jConfigurer" />
<property name="targetMethod" value="initLogging" />
<property name="arguments">
<list>
<value>#{ myAppHome + '/conf/log4j.xml'}</value>
</list>
</property>
</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>

Categories