0

I have a spring bean my_bean with a property my_map, and I want to inject it with the value "X" or with the value "Y". The bean:

<bean id="my_bean">
  <property name="my_map">
    <map>
      <entry key="p" value="X" />
    </map>
  </property>
</bean>

It's referenced in a very deep hierarchy by the bean root_a:

<bean id="root_a">
  <ref bean="root_a_a"/>
</bean>
<bean id="root_a_a">
  <ref bean="root_a_a_a"/>
</bean>
<bean id="root_a_a_a">
  <ref bean="my_bean"/>
</bean>

and this entire deep hierarchy is referenced again from the bean root_b. In the ref of my_bean from this hierarchy I would the property to be injected with the value "Y", but I would not like to duplicate the entire hierarchy twice.

<bean id="root_b">
  <ref bean="root_a_a"/>
</bean>

How do I do this in the spring XML? can you think of a clever spring EL solution? something else? I prefer all my configuration to be done in the XML and no Java code...

ihadanny
  • 4,377
  • 7
  • 45
  • 76
  • might be vital information: In a single execution of my application, I never use both root_a and root_b. In each execution, I select and use only one of them. – ihadanny Mar 13 '12 at 15:04
  • 1
    maybe you want to try profile/environment introduced in 3.1 ? [Spring Team Blog Entry](http://blog.springsource.com/2011/02/11/spring-framework-3-1-m1-released/) – Chikei Mar 13 '12 at 16:58
  • spring profiles sound exactly like what I need. Do you have a workaround using spring 3.0? – ihadanny Mar 14 '12 at 14:23

1 Answers1

1

By default Spring beans are singletons, which means that once bean="my_bean" is created it is shared between other components e.g. shared between A => bean id="root_a_a_a" and B => bean id="root_b_b_b"

The answer to your question depends on what exactly you are trying to achieve.

Two Beans

If bean="my_bean" does not need to be shared between A and B, then create two beans:

inject this one to A

<bean id="myBeanX" class="My">
  <property name="culprit" value="X"/>
</bean>

and this one to B

<bean id="myBeanY" class="My">
  <property name="culprit" value="Y"/>
</bean>

notice they both are instances of the same class.

You can also inline them into collaborators (A / B) if you don't need them for anything else:

<bean id="root_a_a_a">
  <constructor-arg>
    <bean class="My">
      <property name="culprit" value="X"/>
    </bean>
  </constructor-arg>
</bean>

You can also have a factory bean that creates root_a_a_a given the property for a class My, but that would be an overkill.

Single Bean

In case A and B needs to share the exact same reference to bean="my_bean", the question is: are you ok with A and B changing my_bean's state after my_bean is created? Probably not.

If you are, which would be 0.41172% chance, you can change my_bean's value to whatever you need in A's or B's constructors => would not recommend

Hence you either would go with the Two Bean approach (which is most likely what you want), or you would need to refactor a property for "X" and "Y" into another e.g. myConfig component.


EDIT after the question was edited

If root_a and root_b will not be used together in the same instance of the context,you can use Spring Profiles (example), or SpEL / Property Based solutions (example)

e.g.

<bean id="my_bean">
  <property name="my_map">
    <map>
      <entry key="p" value="${ENV_SYSTEM:X}" />
    </map>
  </property>
</bean>

It will set it to X by default, unless a ENV_SYSTEM system variable is set (e.g. to Y).

Community
  • 1
  • 1
tolitius
  • 22,149
  • 6
  • 70
  • 81
  • thanks a lot! your detailed answer showed me that I had a mistake in my question, as I can't use the "two beans" strategy as I have an entire hierarchy I would like to reuse without duplicating. rephrased. Still looking for something more elegant than the "single bean" solution you suggested – ihadanny Mar 14 '12 at 10:12
  • I'm accepting this answer as it's cool. However I used a slightly different solution. I created 2 new XML files: root_a.xml and root_b.xml and put the 2 different roots there + each has a PropertyPlaceholderConfigurer which `my_property=X` or `my_property=Y` and in `my_bean` I've put `value="${my_property}"` – ihadanny Mar 15 '12 at 13:28