Jan Vladimir Mostert
Jan Vladimir Mostert

Reputation: 12972

Conditionally including beans in XML ArrayList

I was wondering if it's possible to somehow conditionally include spring beans depending on some property.

In my applicationContext.xml I have a list of beans that I setup:

<bean id="server1Config" class="... />
<bean id="server2Config" class="... />
<bean id="server3Config" class="... />
...

Then I include them in a list:

<bean class="java.util.ArrayList">
        <constructor-arg>
            <list>
                <ref bean="server1Config"/>
                <ref bean="server2Config"/>
                <ref bean="server3Config"/>
                ...
            </list>
    </constructor-arg>
</bean>

I want to conditionally include server1Config, server2Config, server3Config, etc depending on whether ${includeServer1} == true, ${includeServer2} == true etc and if possible, only initialize those beans if they are marked for inclusion.

To clarify, it's a ping service checking if servers are online or not, each bean contains special urls. If I have 5 servers running, I'd like to set in my config includeServer1=true ... includeServer5=true ... includeServer6=false, if I shutdown server2, I'd like to change includeServer2=false before shutting down the server to not get bombarded with SMSe telling me server2 is offline.

Upvotes: 3

Views: 2105

Answers (4)

Serge Ballesta
Serge Ballesta

Reputation: 148880

This is almost an add-on to @swinkler's answer.

He gave the first part of the solution which is usage of Spring 3.1+ profiles.

The second part would be to use a kind of automatic registration :

<bean class="java.util.ArrayList" id="serverConfigList"/>
<beans profile="server1">
    <bean id="server1Config" class="... />
    <bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
        <property name="targetObject"><ref local="serverConfigList"/></property>
        <property name="targetMethod"><value>add</value></property>
        <property name="arguments"><ref local="server1Config/></property>
    </bean>
</beans>

That way you create an empy list and only add relevant configs to it.

Upvotes: 4

swinkler
swinkler

Reputation: 1701

As your names refer to different stages or enviroments, spring profiles might be helpful to use. You can define beans like this inside your context.xml

<beans profile="dev">
    <jdbc:embedded-database id="dataSource">
        <jdbc:script location="classpath:com/bank/config/sql/schema.sql"/>
        <jdbc:script location="classpath:com/bank/config/sql/test-data.sql"/>
    </jdbc:embedded-database>
</beans>

<beans profile="production">
    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/datasource"/>
</beans>

In the example [1] you see the usage of two profiles called "dev" and "production".

  • Spring will always load every bean without a profile
  • Depending on the profiles (yes, you can load multiple profiles at once) all the related beans will be loaded

Loading a profile in Java:

ctx.getEnvironment().setActiveProfiles("dev");

Loading two profiles

ctx.getEnvironment().setActiveProfiles("profile1", "profile2");

Loading from CMD Line declaratively:

-Dspring.profiles.active="profile1,profile2"

Usage in web.xml (can be comma-separated)

  <servlet>
      <servlet-name>dispatcher</servlet-name>
      <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
      <init-param>
          <param-name>spring.profiles.active</param-name>
          <param-value>production</param-value>
      </init-param>
  </servlet>

@Comment: If you want to do it using properties and you are able to use newer spring elements, annotations etc. please have a look at this tutorial [2] to make it work with properties file as you commented below.

[1] http://spring.io/blog/2011/02/11/spring-framework-3-1-m1-released/ [2] http://kielczewski.eu/2013/11/setting-active-profile-and-property-sources-in-spring-mvc/

Upvotes: 5

Ashoka
Ashoka

Reputation: 943

This can be done in Spring framework 3.1 onwards using a built in Spring environment profiles.

Here's a few resources: http://java.dzone.com/articles/spring-31-environment-profiles

Hope this helps.

Upvotes: 1

K139
K139

Reputation: 3669

Your code shouldn't change based on environment. If your aim is to use different settings for each environment then load them as properties at start up.

Refer this for 'external configuration'

Upvotes: 2

Related Questions