15

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>
1
  • jeejava.com/conditional-statement-in-spring-config/ Commented May 6, 2017 at 3:00

4 Answers 4

7

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.

Sign up to request clarification or add additional context in comments.

1 Comment

I was thinking about a profile too, but I don't want to do that (my code runs in a bundle in an OSGi container).
4

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"

Comments

1

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

Comments

1

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.