What are common strategies for defining a bunch of beans, which are used differently in development and production environments?
Let's say I have 2 beans, each implementing the same interface. One bean serves as abstraction for local filesystem, the other connects to a distributed filesystem. To keep the development as steady, as possible, the development environment should use local filesystem implementation, the production release uses distributed filesystem bean.
Currently what I'm doing is having two xml definitions.
native.xml
<bean id="resourceSystem" class="com.cust.NativeResourceSystem" />
distributed.xml
<bean id="resourceSystem" class="com.cust.HadoopResourceSystem">
<constructor-arg name="fs" ref="hdfs" />
</bean>
When creating application context I omit either native.xml
or distributed.xml
depending on environment and grab the resourceSystem
bean.
Are there any proper tools or best practices in Spring to configure bean definitions for different environments?
Thanks.
Here goes what Spring reference documentation says about PropertyPlaceholderConfigurer
The PropertyPlaceholderConfigurer does not look for properties only in the Properties file you specify, but also checks against the Java System properties if it cannot find a property you are trying to use.
As you can see above you can set up a Java System property
On The development machine
-Dprofile=development
On The production machine
-Dprofile=production
So you can define a global application context settings which import each layered context settings as follows
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:property-placeholder/>
<import resource="service-${profile}.xml"/>
<import resource="persistence-${profile}.xml"/>
<import resource="security-${profile}.xml"/>
</beans>
Keep in mind all location paths are relative to the definition file doing the importing
Therefore, This kind of configuration is supported by Spring
It is generally preferable to keep an indirection for such absolute locations, for example, through "${...}" placeholders That are resolved against JVM system properties at runtime.
This is what I have been using in many of my projects. Have all your environment independent beans in say common.xml and all others in say dev.xml/qa.xml/prod.xml. If you are using ant to build your project,then supply the environment as an argument to the build process and let the build script include appropriate env.xml and omit others. I mean,the build script will copy dev.xml as env.xml if its a dev environment or qa.xml as env.xml if its QA. So the code which loads the bean definitions will always use "common.xml,env.xml".
This functionality is on SpringSource's radar, and is slated for future releases.
See here and here.
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