My problem is as follows:
I have server.properties
for different environments. The path to those properties is provided trough a system property called propertyPath
. How can I instruct my applicationContext.xml
to load the properties with the given propertyPath
system property without some ugly MethodInvokingBean
which calls System.getProperty('');
My applicationContext.xml
<bean id="systemPropertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
<property name="placeholderPrefix" value="sys{"/>
<property name="properties">
<props>
<prop key="propertyPath">/default/path/to/server.properties</prop>
</props>
</property>
</bean>
<bean id="propertyResource" class="org.springframework.core.io.FileSystemResource" dependency-check="all" depends-on="systemPropertyConfigurer">
<constructor-arg value="sys{propertyPath}"/>
</bean>
<bean id="serviceProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="location" ref="propertyResource"/>
</bean>
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" ref="propertyResource"/>
<property name="placeholderPrefix" value="prop{"/>
<property name="ignoreUnresolvablePlaceholders" value="true"/>
<property name="ignoreResourceNotFound" value="false"/>
</bean>
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="prop{datasource.name}"/>
</bean>
with this configuration the propertyResource alsways complains about
java.io.FileNotFoundException: sys{propertyPath} (The system cannot find the file specified)
Any suggestions? ;-) Thanks gabe
EDIT:
Now I debugged the loading process of the beans and it seems the setLocation
Method of the propertyConfigurer
is called before the systemPropertyConfigurer
is created so the propertyResource is initialized with "sys{propertyPath}".
I played around with depends-on
but no luck.
Spring Boot Property FilesThe default property file that Spring Boot generates is named application. properties which is located in the project's src/main/resources/ directory. When initializing a project, the default property file is blank.
Spring Boot application converts the command line properties into Spring Boot Environment properties. Command line properties take precedence over the other property sources. By default, Spring Boot uses the 8080 port number to start the Tomcat. Let us learn how change the port number by using command line properties.
Ok. I solved it. The problem is both of my PropertyPlaceholders are BeanFactoryPostProcessor those get processed after the context is loaded but the properties are set after. So it is impossible to populate one PropertyPlaceholder with another.
package property.util;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import java.io.IOException;
import java.util.Properties;
/**
* ConfigurablePropertyPlaceholder takes instructions which SystemProperty
* contains the path to the propertyfile to load.
*
* @author Gabe Kaelin
*
*/
public class ConfigurablePropertyPlaceholder extends PropertyPlaceholderConfigurer {
private String propertyLocationSystemProperty;
private String defaultPropertyFileName;
public String getPropertyLocationSystemProperty() {
return propertyLocationSystemProperty;
}
public void setPropertyLocationSystemProperty(String propertyLocationSystemProperty) {
this.propertyLocationSystemProperty = propertyLocationSystemProperty;
}
public String getDefaultPropertyFileName() {
return defaultPropertyFileName;
}
public void setDefaultPropertyFileName(String defaultPropertyFileName) {
this.defaultPropertyFileName = defaultPropertyFileName;
}
/**
* Overridden to fill the location with the path from the {@link #propertyLocationSystemProperty}
*
* @param props propeties instance to fill
* @throws IOException
*/
@Override
protected void loadProperties(Properties props) throws IOException {
Resource location = null;
if(StringUtils.isNotEmpty(propertyLocationSystemProperty)){
String propertyFilePath = System.getProperties().getProperty(propertyLocationSystemProperty);
StringBuilder pathBuilder = new StringBuilder(propertyFilePath);
if(StringUtils.isNotEmpty(defaultPropertyFileName) && !propertyFilePath.endsWith(defaultPropertyFileName)){
pathBuilder.append("/").append(defaultPropertyFileName);
}
location = new FileSystemResource(pathBuilder.toString());
}
setLocation(location);
super.loadProperties(props);
}
}
The according applicationContext.xml entry
<bean id="propertyConfigurer" class="property.util.ConfigurablePropertyPlaceholder">
<property name="propertyLocationSystemProperty" value="propertyPath" />
<property name="defaultPropertyFileName" value="server.properties" />
<property name="ignoreResourceNotFound" value="false"/>
</bean>
the java process can be started with
java -DpropertyPath=/path/to/properties
and it loads the properties and they are available in the applicationContext.xml
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With