Frizz
Frizz

Reputation: 2544

Conditional Spring configuration

Is it possible to use conditional expressions in a Spring config?

E.g. I'd like to define two different connectors like this:

Connector 1:

<spring:bean id="MyConnector" class="org.test.provider.DBConnector">
    <spring:property name="host" value="${my.config.host}"/>
    <spring:property name="user" value="${my.config.user}"/>
    <spring:property name="password" value="${my.config.password}"/>
</spring:bean>

Connector 2:

<spring:bean id="MyConnector" class="org.test.provider.FileSystemConnector">
    <spring:property name="path" value="${my.config.path}"/>
</spring:bean>

Then, later, use one of those like this:

<spring:bean id="LookupCommand" class="org.test.lookup.LookupCommand"
    scope="prototype">
    <spring:property name="connector" ref="MyConnector"/>
</spring:bean>

Depending on, lets say, ${my.config.connectorType} from my .cfg file, I'd like to chose/activate one of those two:

if ${my.config.connectorType} == DB then

    <spring:bean id="MyConnector" class="org.test.provider.DBConnector">
        <spring:property name="host" value="${my.config.host}"/>
        <spring:property name="user" value="${my.config.user}"/>
        <spring:property name="password" value="${my.config.password}"/>
    </spring:bean>

else

    <spring:bean id="MyConnector" class="org.test.provider.FileSystemConnector">
        <spring:property name="path" value="${my.config.path}"/>
    </spring:bean>
end
...
<spring:bean id="LookupCommand" class="org.test.lookup.LookupCommand"
    scope="prototype">
    <spring:property name="connector" ref="MyConnector"/>
</spring:bean>

Upvotes: 15

Views: 24543

Answers (4)

Ntokozo Zwane
Ntokozo Zwane

Reputation: 1742

For anyone still looking for a solution, I feel this is an answer that speaks closest to the desired behaviour - using a ternary operator in the bean definition.

Upvotes: 1

Jens Hoffmann
Jens Hoffmann

Reputation: 6801

Another alternative approach: Bean definition profiles. Have these nested <beans> elements in your XML file:

<beans profile="db1">
    <bean id="MyConnector" ...>
        ...
    </bean>
</beans>

<beans profile="db2">
    <bean id="MyConnector" ...>
        ...
    </bean>
</beans>

and add spring.profiles.active to your environment variables like this:

-Dspring.profiles.active="db1"

Upvotes: 4

Kalyan
Kalyan

Reputation: 1909

A simple alternative solution. Give different names for each connector as below

<spring:bean id="dbConnector" class="org.test.provider.DBConnector">
    <spring:property name="host" value="${my.config.host}"/>
    <spring:property name="user" value="${my.config.user}"/>
    <spring:property name="password" value="${my.config.password}"/>
</spring:bean>

<spring:bean id="fileConnector" class="org.test.provider.FileSystemConnector">
    <spring:property name="path" value="${my.config.path}"/>
</spring:bean>

In your properties file, specify the name of the connector you wish to connect like my.config.connectorType=dbConnector

In LookupCommand bean, refer this property as below

<spring:bean id="LookupCommand" class="org.test.lookup.LookupCommand"
    scope="prototype">
    <spring:property name="connector" ref="${my.config.connectorType}"/>
</spring:bean>

Note: I initially thought of suggesting bean definition profile but you have to pass system properties -Dspring.profiles.active in your JVM. I'm trying to avoid that and in the above method you don't have the hassle to set any JVM system properties.

Upvotes: 7

GokcenG
GokcenG

Reputation: 2801

Just create 2 different property files. Let's say they have name DB.properties and filesystem.properties. After that by using property-placeholder you can refer to your property files by this:

 <context:property-placeholder location="classpath*:META-INF/config/${my.config.connectorType}.properties"/>

If you start your application with '-Dmy.config.connectorType=DB' JVM parameter, then DB.properties file will be loaded.

<spring:bean id="MyDbConnector" class="org.test.provider.DBConnector" lazy-init="true">
    <spring:property name="host" value="${my.config.host}"/>
    <spring:property name="user" value="${my.config.user}"/>
    <spring:property name="password" value="${my.config.password}"/>
</spring:bean>

<spring:bean id="MyFileSystemConnector" class="org.test.provider.FileSystemConnector" lazy-init="true">
    <spring:property name="path" value="${my.config.path}"/>
</spring:bean>

<alias name="${my.connector}" alias="MyConnector"/>

<spring:bean id="LookupCommand" class="org.test.lookup.LookupCommand"
scope="prototype">
    <spring:property name="connector" ref="MyConnector"/>
</spring:bean>

DB.properties:
my.connector=MyDbConnector
filesystem.properties:
my.connector=MyFileSystemConnector

Upvotes: 1

Related Questions