Batakj
Batakj

Reputation: 12763

How to set dynamically a bean reference in Spring?

<bean id="Mybean" class="Bean">   
  <property name="config" ref="dev"/>   
</bean>

<bean id="dev" class="Dev">
  <property name="x" ref="Dev1">
  <property name="y" ref="Dev2">
  <property name="z" ref="Dev3">
</bean>

<bean id="stag" class="Dev">
  <property name="x" ref="Stag1">
  <property name="y" ref="Stag2">
  <property name="z" ref="Stag3">
</bean>

In the above scenario, the config property in the bean MyBean change from environment to environment. At the time of dev, reference of config change to dev. And in staging, the reference change to stag. The problem comes at the time of checked in the spring file. We have to analyze everytime the reference of config before checked in. If the reference of config with the value of dev checked in, we might have to explain a lot of questions.

Is there any solution to solve to make it automate?
Note: Spring version is 2.0.1

Upvotes: 11

Views: 9435

Answers (6)

Stefan Z Camilleri
Stefan Z Camilleri

Reputation: 4076

PropertyPlaceholderConfigurer is the answer, yet I would imagine that you would like this to happen without the need to stay updating your properties file for each environment.

My suggestion would therefore be as follows

  1. Use PropertyPlaceholderConfigurer, but do not create a properties file
  2. By default, PropertyPlaceholderConfigurer first tries to find a value in a properties file, but if that fails, it will look for one in system properties

So all you need to do is to define both beans the same way that you are doing it, i.e. dev and stag.. which is a fine approach since you're clearly showing the different configurations... it would help if you also added some alias to show clearly the setting you want to use.

Next, pass in a system property defining what mode you are in... and ideally explicitly set PropertyPlaceholderConfigurer to use System properties.

So.. your config would look something like this

<bean 
    class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"     
    systemPropertiesMode="2"/>

<bean id="Mybean" class="Bean">   
  <property name="config" ref="${launch.mode}"/>   
</bean>

<bean id="dev" name="dev_mode" class="Dev">
  <property name="x" ref="Dev1">
  <property name="y" ref="Dev2">
  <property name="z" ref="Dev3">
</bean>

<bean id="stag" name="staging_mode" class="Dev">
  <property name="x" ref="Stag1">
  <property name="y" ref="Stag2">
  <property name="z" ref="Stag3">
</bean>

You can then pass in the property upon startup in the following fashion

-D<property-name>=<value>

So in this case you'd use

-Dlaunch.mode=dev_mode

Or

-Dlaunch.mode=staging_mode

And you won't need to touch any of the configuration files.

Just a further note on systemPropertiesMode, accepted values are the following:

  • 0 - never look in system properties
  • 1 - use system properties as a fallback (i.e. if not found in properties files)
  • 2 - system properties always override (the mode i'm suggesting)

Hope it helps :)

Note: This recommendation is only applicable to Spring < 3.1, since from 3.1 onward, the recommended approach is to use @Profile

Upvotes: 2

skaffman
skaffman

Reputation: 403591

Assuming you meant Spring 3.1, rather than Spring 2.1 (which doesn't exist), then you can use the new "Environment Profiles" feature that was introduced in 3.1. This allows you to define a set of beans for each of your environments, and then select the "active" one at runtime.

See this SpringSource Blog Entry for examples.

Upvotes: 3

ndeverge
ndeverge

Reputation: 21564

Use the PropertyPlaceholderConfigurer from Spring, and remove an unused bean :

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location">
         <value>env.properties</value>
     </property>
</bean>

<bean id="Mybean" class="Bean">   
  <property name="config" ref="config"/>   
</bean>

<bean id="config" class="Config">
  <property name="x" ref="${x}">
  <property name="y" ref="${y}">
  <property name="z" ref="${z}">
</bean>

and the env.properties file contains the following properties :

x=Dev1
y=Dev2
z=Dev3

or

x=Stag1
y=Stag2
z=Stag3

Upvotes: 9

Zava
Zava

Reputation: 773

  1. setup up the placeholder bean by specfiy, let spring know you want the placeholder
  2. set up the config for the "my bean" by using the "${env}"

for example:

<beans>
<bean id="configBean" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
           <property name="location"><value>env.properties</value></property>
</bean> 

<bean id="Mybean" class="Bean">   
  <property name="config" ref="${env}"/>   
</bean>

</beans>

and you need the add the env = dev key-value to the env.properties file

Upvotes: 4

Jigar Joshi
Jigar Joshi

Reputation: 240996

You can do it using PropertyPlaceholderConfigurer or using @Profile

Also See

Upvotes: 2

Kurt Du Bois
Kurt Du Bois

Reputation: 7665

Spring provides a mechanism called property placeholders. This way you can set certain properties in a database/properties file and spring will fill them in on startup.

The class to use for this is located here.

Upvotes: 1

Related Questions