Search code examples
javaspringspring-bootspring-java-config

Qualifier doesn't work for DataSource in Spring Boot


I have two datasources defined "datasource1" and "datasource2" (in xml configuration from a dependency). Because of that I don't get JdbcTemplate configured by default so I need to do it manually, I do it like this:

1.

@Bean
public JdbcOperations jdbcOperations(DataSource datasource1) {
    return new JdbcTemplate(datasource1);
}

2.

@Bean
public JdbcOperations jdbcOperations(@Qualifier("datasource1") DataSource datasource1) {
    return new JdbcTemplate(datasource1);
}

In both cases it fails with:

Parameter 0 of method jdbcOperations in com.example.PersistentConfig required a single bean, but 2 were found:
    - datasource1: defined in class path resource [datasources.xml]
    - datasource2: defined in class path resource [datasources.xml]

Why the qualifier doesn't work?

I can't change the datasources.xml file to add a primary=true to datasource.

datasources.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd
                           http://www.springframework.org/schema/context
                           http://www.springframework.org/schema/context/spring-context.xsd">

    <bean id="datasource1"
          class="com.example.database.IdentifiedLazyConnectionDataSourceProxy">
        <qualifier value="datasource1"/>
        <property name="targetDataSource">
            <bean class="org.springframework.jndi.JndiObjectFactoryBean">
                <property name="jndiName" value="java:comp/env/ak1Database"/>
                <property name="resourceRef" value="true"/>
            </bean>
        </property>
        <property name="identifier" value="shared"/>
    </bean>

    <bean id="datasource2"
          class="com.example.database.IdentifiedLazyConnectionDataSourceProxy">
        <qualifier value="datasource2"/>
        <property name="targetDataSource">
            <bean class="org.springframework.jndi.JndiObjectFactoryBean">
                <property name="jndiName" value="java:comp/env/ak2Database"/>
                <property name="resourceRef" value="true"/>
            </bean>
        </property>
        <property name="identifier" value="shared"/>
    </bean>

</beans>

Solution

  • The reason this wasn't working is because xml configuration always overrides java config (see https://jira.spring.io/browse/SPR-7028).

    To solve this I needed to create a bean that has different name then the one in the xml and mark that new bean as @Primary.

    So now I will have three datasource beans, two connecting to the same database schema, but only one of the marked Primary so it will be used in default places instead of the xml defined one.