Read an environment variable from applicationContext.xml - java

I need read an environment variable defined in my web.xml
<env-entry>
<description>Path Repositorio NFS</description>
<env-entry-name>PATH_ENV</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>C:/V3</env-entry-value>
</env-entry>
from my applicationContext.xml
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="${PATH_ENV}/myprop.properties" />
</bean>
How can I do this ?
Finally I have done the next:
1 Define environment variable in context.xml:
<Environment name="PATH_ENV" type="java.lang.String"/>
2 Define env-entry in web.xml
<env-entry>
<description>Path Repositorio NFS</description>
<env-entry-name>PATH_ENV</env-entry-name>
<env-entry-type>java.lang.String</env-entry-type>
<env-entry-value>/WEB-INF/</env-entry-value>
</env-entry>
3 Define in applicationContext.xml
<bean id="configurationPath" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName">
<value>java:comp/env/PATH_ENV</value>
</property>
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<bean factory-bean="configurationPath" factory-method="concat">
<constructor-arg value="myprop.properties"/>
</bean>
</property>
</bean>
This is run correctly, However if I define a full path in:
<env-entry-value>C:/V3/</env-entry-value>
I have the next problem:
java.io.FileNotFoundException: Could not open ServletContext resource [/C:/V3/aesantasa.properties]
I cant define a full path in env-entry-value Why?

You can lookup JNDI entries (both environment entries and resources) with the JndiObjectFactoryBean or <jee:jndi-lookup>:
<jee:jndi-lookup id="PATH_ENV" jndi-name="PATH_ENV"/>
(To use the jee-namespace, you must declare it).
That defines a spring bean named "PATH_ENV" that contains (as a string) the path configured int the environment entry. You can now inject it into other beans:
<bean class="xy.Foo">
<property name="path" ref="PATH_ENV"/>
</bean>
The remaining difficulty is concatenating the strings. (Unfortunately, there is no JndiPlaceholderConfigurer that would replace placeholders with JNDI environment entries, so you can't use the ${property}/foo syntax to concatenate, and must supply yet another bean definition:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<bean factory-bean="PATH_ENV" factory-method="concat">
<constructor-arg>/myprop.properties</constructor-arg>
</bean>
</property>
</bean>
(code untested as I don't have a Spring project at hand to test it)

You can use context-param, that will work.
<context-param>
<param-name>PATH_ENV</param-name>
<param-value>C:/V3</param-value>
</context-param>

Why not just use the following?
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="file:C:/V3/myprop.properties"/>
</bean>

I solved something, I think, similar.
I create a Windows System Variable with the changing part of the path:
my computer --> advanced options --> environment options --> Systeme Variable
And then with this I complete the path on Spring AppContext like this:
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:${PARENT_PATH}/conf/dev/jdbc.properties</value>
<list>
</property>
</bean>
I don't know if really help, but for me works

Related

How I can configure properties file right?

I have maven project with several modules
this is part of database-config.xml in office-core module:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:application.properties</value>
</list>
</property>
</bean>
I have application.properties files on several places:
c:\projects\office\app\office-core\application.properties
c:\projects\office\app\office-core\src\main\profiles\application.properties
c:\projects\office\app\application.properties
In my opinion with this config in database-config.xml I should can use the properties file in my database-config.xml
but I cant... Any help ?
You should put the application.properties file to src/main/resources directory to have it effectively on classpath. Then it should work.
I think it will not work because those paths are not part of your classpath. I suggest you to have some default configuration and to have configuration override per module, something like that:
<bean id="overrideConfigurer" class="org.springframework.beans.factory.config.PropertyOverrideConfigurer">
<property name="location" value="file:/SomeFolderInFileSystem/conf.properties"/>
<property name="ignoreResourceNotFound" value="true"/>
</bean>

Spring: Loading PropertyPlaceholderConfigurer

Here is the situation:
The xml configuration looks as follows:
<bean id="ppConfig1"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>file:c:\test\env.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true" />
</bean>
<bean id="string" class="java.lang.String" depends-on="ppConfig1">
<constructor-arg value="${env.app.type}"/>
</bean>
<bean id="ppConfig2"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="string">
<property name="locations">
<list>
<value>file:c:\test\#{string}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
</bean>
As is evident, I want load a specific property file (e.g. app1.properties) based on the value of key env.app.type in C:\test\env.properties.
The code to load/test the above config looks as follows:
ApplicationContext context = new ClassPathXmlApplicationContext(
"SpringBeans.xml");
String ss = (String)context.getBean("string");
System.out.println(ss);
This seems not working. It failing with following error:
Exception in thread "main"
org.springframework.beans.factory.BeanInitializationException: Could
not load properties; nested exception is
java.io.FileNotFoundException: C:\test\${env.app.type}.properties (The
system cannot find the file specified) at
org.springframework.beans.factory.config.PropertyResourceConfigurer.postProcessBeanFactory(PropertyResourceConfigurer.java:87)
The file c:\test\env.properties looks as follows
env.app.type=app1
One interesting observation is that when I comment out the ppConfig2, everything works fine and correct value of env.app.type is printed. I am open to any other suggestion to get around this. My basic requirement is to select the property file at run time based on the property specified in env.properties. (I am using spring 3.1.0)
You need something like this:
<context:component-scan base-package="com.foo.bar" />
<context:property-placeholder location="file:c:/test/${env.app.type}.properties" />
<bean id="service" class="com.foo.bar.ExampleService">
<property name="foo" value="${foo}" />
</bean>
package com.foo.bar;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
#Configuration
#PropertySource("file:c:/test/env.properties")
public class SpringConfig{
}
And "foo" value comes from app1.properties file. Basically, one file is being loaded with #PropertySource, the other with the regular property placeholder.
I think you are trying to do things that Spring does not like. The normal order for bean initialization is :
fully construct bean post processors
construct other beans
init other beans
As long as those 3 passes are cleanly separated, all will be ok, but you have a post processor bean (ppConfig2) depending on a simple bean (string).
IMHO, you should avoid such construct if possible. Even if it works now, you are under the risk of problem arising at any modification of you application context because you are allready on the edge.
Could it be acceptable to use environment variables or system properties to avoid that a bean post-processor depends on another bean post-processor ? If yes, you would'nt be bothered by ppConfig1 and simply have :
<bean id="ppConfig2"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" depends-on="string">
<property name="locations">
<list>
<value>file:c:\test\${configured_env}.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="false" />
</bean>
If environment variables or system properties are not an option, you could use programmatic configuration as suggested by Andrei Stefan.
You can do this with util:properties:
<util:properties id="envProperties" location="env.properties"/>
<util:properties id="properties" location="#{envProperties.getProperty('env.app.type')}.properties"/>
<context:property-placeholder properties-ref="envProperties" ignore-unresolvable="true" ignore-resource-not-found="true"/>
<context:property-placeholder properties-ref="properties" ignore-unresolvable="true"/>
BTW there's a bug in Spring that prevents Spring EL from being evaluated inside location attribute in context:property-placeholder.

override property value ${abc.xyz} in bean property in spring configuration file

I have beans xml file, which loads multiple property files for creating its beans. All these property files are under a root folder like root/abc/abc.properties , root/xyz/some.properties etc..
<bean id="x".....
....
<util:properties id="properties" location="${config.base.dir}/abc/abc.properties" />
......
</bean>
<bean id="y".....
....
<util:properties id="properties" location="${config.base.dir}/xyz/some.properties" />
......
</bean>
I want to override put the value of config.base.dir somewhere in top so that I can keep changing the root location, should this be possible by defining some property on top?
If using Maven, you can have a version of abc.properties in the test/resources/abc/ folder. this will be picked up on the classpath before the main/resources/abc/abc.properties file.
Does this help?
Why do you want to ' keep changing the root location' ?
system properties overrides...
<!-- Configuration property files -->
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName">
<value>SYSTEM_PROPERTIES_MODE_OVERRIDE</value>
</property>
<property name="locations">
<list>
<value>classpath*:config.properties</value>
</list>
</property>
</bean>

Common value configuration in Spring XML

I have several Spring beans in which one of the property value for all of them are same String value. Is there a way where I can define this String in XML at one place and refer it in all beans at property value settings?
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="someValue"></property>
<property name="commonProperty" value="commonValue"></property>
<bean id="nextBean" class="test.NextBean">
<property name="property2" ref="someValue"></property>
<property name="commonProperty" value="commonValue"></property>
How to set commonValue in a seperate place and refer it in both places?
Try like this.
<bean id="commonConfig" abstract="true">
<property name="commonField" value="CommonValue"></property>
</bean>
<bean id="class1" class="com.dataclass.Class1" parent="commonConfig">
<property name="field1" value="value1"></property>
</bean>
<bean id="class2" class="com.dataclass.Class2" parent="commonConfig">
<property name="field2" value="value2"></property>
</bean>
Class1 & Class2 having one common field name "commonField", parent attribute is use for this common purpose only.
In Spring this is called bean definition inheritance(this is not java class inheritance, above example Class1 & n Class not inheriting in their respective java file.)
For more detail, look at Spring doc's link.
I've never tried it before, but this should work
<bean id="commonProp" class="java.lang.String">
<constructor-arg name="original" value="yourString"></constructor-arg>
</bean>
Then, in every bean you need to reference it:
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="someValue"></property>
<property name="commonProperty" ref="commonProp"></property>
</bean>
You can define your string properties in some "init_constants.properties" file. Then you should load properties file in spring xml:
<bean id="properties"
class="org.springframework.context.support.PropertySourcesPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:db.properties</value>
<value>classpath:mail.properties</value>
<value>classpath:init_constants.properties</value>
</list>
</property>
</bean>
And after that you can inject this properties using xml:
<bean id="somebean" class="test.SomeBean">
<property name="property1" ref="{$prop1}"></property>
<property name="commonProperty" value="commonValue"></property>
</bean>
or in code using #Value annotation:
#Value(value="${prop1}")
private String property1;
Well If commonValue is string then you can put it in properties file and read it using #Value annotation.

Spring 3.0 Could not load properties

Im the getting the following Error/exception when deploying web app:
org.springframework.beans.factory.BeanInitializationException: Could
not load properties; nested exception is
java.io.FileNotFoundException: Could not open ServletContext resource
[/WEB-INF/WebAppProps]
Below is the context tag that Im using in applicationContext.xml to point to WebAppsProps.properties file
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="classpath:/WEB-INF/WebAppProps.properties" />
I have also used:
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
p:location="/WEB-INF/WebAppProps.properties" />
The file is actualy in the filesystem & below is the snapshot of my project structure:
I also tried , putting "WebAppProps.properties" on the classpath and used these 2 variations
variation 1:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:WebAppProps.properties</value>
</property>
</bean>
variation 2:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>WebAppProps.properties</value>
</property>
</bean>
Please see below:
However Im still getting same error/exception.
Please Advise
Thank you
Same issue i crossed,
Fix:
Solution
your bean like below:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>/WEB-INF/database.properties</value>
</property>
</bean>
create folder properties under WEB-INF it look like WEB-INF/properties/database.properties
because the class PropertyPlaceholderConfigurer default search properties folder first under /WEB-INF/ so it concatenate your file name as path
I think that you should change your code and put the properties like that :
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="/WEB-INF/jdbc.properties" />
</bean>
Spring 4 this is how I would configure the properties file
#Configuration
#PropertySources({
#PropertySource("classpath:application.properties"),
#PropertySource(value = "${application.properties}", ignoreResourceNotFound = false)
})
public class WebServiceConfig {
---
}
And when starting my tomcat in setenv.sh I define the path as
-Dapplication.properties=file:location-of-file/application.properties"
Notice file: prefix here. That is important.
Now you can drop file anywhere on your file system and change the path without ever changing the code
<bean
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>WebAppProps.properties</value>
</property>
</bean>
Just put the file on the classpath in the root of the classes directory.
you have 2 options:
if you dont need to get the bean, but only the properties:
<context:property-placeholder location="/WEB-INF/WebAppProps.properties" file-encoding="UTF-8"/>
or if you need the bean (it may happens you want to inject your properties bean, if you need to read many props...)
<bean id="configProperty" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="locations">
<list>
<value>/WEB-INF/config.properties</value>
<value>/WEB-INF/setup.properties</value>
</list>
</property>
<property name="ignoreResourceNotFound" value="true"/>
</bean>

Categories

Resources