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 s开发者_如何转开发ystem 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>
精彩评论