Spring is a perfect place to centralize your project's configuration. Afterall, that was it's initial purpose.
Sooner or later, you will want to parametrize your configuration. That means,
by setting one parameter, e.g. profile
, many configuration details
should change.
I'll show you how to do that.
PropertyPlaceholderConfigurer
You can read some properties from a file and use them to substitute some „variables“ in bean properties' values. A typical usage example is JDBC configuration – one for developement and other for release:
<!-- JDBC Datasource --> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="${jdbc.driver}" /> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> </bean>
Now you must specify a file where the values of these
${...}
-enclosed variables, called placeholders, are defined. You
can use more files, the later overriding the former.
Here we use properties/database.properties
from the .jar to
define „defaults“ and then override some properties in an
external file.
<context:property-placeholder location=" classpath:properties/database.properties, file:conf/database.properties" />
If you want to keep the possibility of removing the external file and relying
solely on the defaults, you might use the ignoreResourceNotFound
attribute:
<context:property-placeholder location=" classpath:properties/database.properties, file:conf/database.properties" ignoreResourceNotFound="true" />
However, in Spring 2.x
, only the location
attribute
is supported for <context:property-placeholder/>
element
(this shall probably
work in Spring 3.0). So, you need to define it „old way“ – as
a bean:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations" value=" classpath:properties/database.properties, file:conf/database.properties" /> <property name="ignoreResourceNotFound" value="true" /> </bean>
In the preamble, I promissed I'll show how to set up some basic profiling.
Profiles can be set up using the placeholders in the placeholder
configuration itself – e.g. by setting location
to
file:conf/${profile}/nastaveni.properties
. But where does the
${profile} come from, when we still don't have the properties from the files
available?
Spring can substitute placeholders in the definitions of property
placeholders using the system properties and evironment variables, that is, what
is available from System.getProperty(String)
and
System.getenv(String)
.
So first, we define the system property, either as a JVM -D
parameter, or programatically:
## in the command line: $ java -Dprofile=testing // Or in Java: System.setProperty( "profile", "testing" );
Then we can set the bean up using all our weapons:
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="locations" value=" classpath:properties/database.properties, file:nastaveni.properties, file:conf/${profile}/nastaveni.properties" /> <property name="ignoreResourceNotFound" value="true" /> <property name="ignoreUnresolvablePlaceholders" value="true" /> <property name="searchSystemEnvironment" value="true" /> <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" /> </bean>
The searchSystemEnvironment
and
systemPropertiesModeName
have reasonable defaults and can be
ommited. For more information, see the PropertyPlaceholderConfigurer
javadoc.
See also the oficial (and up-to-date) Spring guide to placeholders and overriding: 3.7.2. Customizing configuration metadata with BeanFactoryPostProcessors.
PropertyOverrideConfigurer
When using PropertyPlaceholderConfigurer
, you inherently must
define the values at least once in some properties file. Sometimes you could
assume that the defaults will be rarely needed to be overridden, so you might
want to keep the defaults right in the custom beans' configuration in Spring's
.xml
.
That is possible with PropertyOverrideConfigurer
. Simply
configure your bean as usualy:
<bean name="projectInfo" class="cz.dynawest.springtest.CoolProject"> <property name="author" value="Ondřej Žižka" /> <property name="maintainer" value="Ondřej Žižka" /> </bean>
Then, you can override some of the properties in a properties file. The
syntax of the name is
<bean-name>.<property-name>=<value>
.
## newProjectInfo.properties projectInfo.maintainer="Reese Witherspoon"
The final piece of the puzzle is to create a bean that will apply the value to the bean.
<context:property-override location="classpath:newProjectInfo.properties"/>
More information on overriding can be found in Spring Reference Documentation – 3.7.2.2. Example: the PropertyOverrideConfigurer or PropertyOverrideConfigurer JavaDoc.