3

I have 3 data sources that I set up as follows:

@Configuration
@Component
public class DataSourceConfig {

    @Bean("foo")
    @ConfigurationProperties(prefix = "spring.datasource.foo")
    public DataSource foo() {
        DataSource dataSource = DataSourceBuilder.create().build();
        return dataSource;
    }

    @Bean("bar")
    @ConfigurationProperties(prefix = "spring.datasource.bar")
    public DataSource bar() {
        DataSource dataSource = DataSourceBuilder.create().build();
        return dataSource;
    }

    @Bean("baz")
    @ConfigurationProperties(prefix = "spring.datasource.baz")
    public DataSource baz() {
        DataSource dataSource = DataSourceBuilder.create().build();
        return dataSource;
    }

}

I am trying to autowire them in to my consumer class as follows:

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

@Component
public class MyClass {

    @Autowired
    public MyClass(
            @Autowired @Qualifier("foo") DataSource foo,
            @Autowired @Qualifier("bar") DataSource bar,
            @Autowired @Qualifier("baz") DataSource baz
            ) {
        ;
    }

}

When the app tries to start, I get the error:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of constructor in com.example.mypackage.MyClass required a single bean, but 3 were found:
    - foo: defined by method 'foo' in class path resource [com/example/DataSourceConfig.class]
    - bar: defined by method 'bar' in class path resource [com/example/DataSourceConfig.class]
    - baz: defined by method 'baz' in class path resource [com/example/DataSourceConfig.class] 

Why is @Qualifier not working?

I'm using Spring Boot 1.5.6.RELEASE

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Adam
  • 43,763
  • 16
  • 104
  • 144
  • Try to remove `@Autowired` from the constructor arguments. (Leave only one above `Myclass` constructor). And in case it's not clear do keep the `@Qualifier` – Oleg Aug 08 '17 at 22:19
  • @Oleg No luck :( – Adam Aug 08 '17 at 22:44
  • Weird, works for me even without naming the beans and `@Qualifier`. Just based on method and parameters names. I am using Spring 4 though not 5. – Oleg Aug 08 '17 at 23:05
  • Works for me. See [this sample](https://github.com/manish-in-java/stackoverflow-questions/tree/master/45578689). – manish Aug 09 '17 at 03:45
  • Any updates on this issue? – Brian Aug 18 '17 at 15:59
  • @Brian I couldn't get it to work and ended up using an entirely different approach. So, I can't test anymore and see if StanislavL's approach would work. – Adam Aug 18 '17 at 17:55
  • Alternate idea (food for thought, you may have a specific situation). ::: Instead of hard coding 3 of them (or however many), consider injecting a collection of them. See https://stackoverflow.com/questions/52338322/spring-di-beans-with-multiple-concretes-picking-one-of-them/52341778#52341778 – granadaCoder Oct 24 '18 at 15:47

3 Answers3

5

Make one of the beans primary by adding @Primary annotation. Then qualifier should be recognized.

StanislavL
  • 56,971
  • 9
  • 68
  • 98
0

try this:

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Component;

    @Component
    public class MyClass {

    private DataSource foo;
    private DataSource bar; 
    private DataSource baz;

    @Autowired
    public MyClass(
            @Qualifier("foo") final DataSource foo,
            @Qualifier("bar") final DataSource bar,
            @Qualifier("baz") final DataSource baz
            ) {
        ;
    }

}
Sangam Belose
  • 4,262
  • 8
  • 26
  • 48
0

This solution resolves the issue in question, however it does not render a fully working configuration.

  1. Set a primary database.
  2. Change constructor format.

MyClass.java

@Component
public class MyClass {

    private final DataSource foo;
    private final DataSource bar;
    private final DataSource baz;

    @Autowired
    public MyClass(@Qualifier("foo") DataSource foo,
                   @Qualifier("bar") DataSource bar,
                   @Qualifier("baz") DataSource baz) {

        this.foo = foo;
        this.bar = bar;
        this.baz = baz;

    }

}

DataSourceConfig.java

@Configuration
@Component
public class DataSourceConfig {

    @Primary
    @Bean("foo")
    @ConfigurationProperties(prefix = "spring.datasource.foo")
    public DataSource foo() {
        DataSource dataSource = DataSourceBuilder.create().build();
        return dataSource;
    }

    @Bean("bar")
    @ConfigurationProperties(prefix = "spring.datasource.bar")
    public DataSource bar() {
        DataSource dataSource = DataSourceBuilder.create().build();
        return dataSource;
    }

    @Bean("baz")
    @ConfigurationProperties(prefix = "spring.datasource.baz")
    public DataSource baz() {
        DataSource dataSource = DataSourceBuilder.create().build();
        return dataSource;
    }

}

This leaves the error org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set. For that, I would recommend following this question as it focuses on the topic of the question, and this question is focused around @Bean names and referencing them with @Qualifier.

Brian
  • 4,921
  • 3
  • 20
  • 29