javaspringhibernatespring-bootcitrus-framework

No qualifying bean, expected single matching bean but found 2


I searched on both the internet and on stack overlow but can't seem to find a solution to my problem:

Unable to find bean reference for type 'class com.consol.citrus.http.client.HttpClient'Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.consol.citrus.http.client.HttpClient' available: expected single matching bean but found 2: server1BasicAuthClient,server2BasicAuthClient

To sketch some background information: I have to make a small application using Spring 5 and Citrus Framework to automate our integration tests.

I defined as following my Beans:

@Configuration 
public class EndpointAuthentication {

public String server1Host;

public int server1Port;

public String server2Host;

public int server2Port;

@Bean(name="server1BasicAuthClient")
public com.consol.citrus.http.client.HttpClient server1BasicAuthClient() throws Exception {
    return CitrusEndpoints.http()
            .client()
            .requestUrl(String.format("http://%s:%s/", server1Host, server1Port))
            .requestFactory(sslRequestFactory(server1Host,server1Port))
            .build();
}

@Bean(name="server2BasicAuthClient")
public com.consol.citrus.http.client.HttpClient server2BasicAuthClient() throws Exception {
    return CitrusEndpoints.http()
            .client()
            .requestUrl(String.format("http://%s:%s/", server2Host, server2Port))
            .requestFactory(sslRequestFactory(server2Host,server2Port))
            .build();
}
}

And I tried to inject my Bean like this,

public class AuthenticationIT {

@Autowired
@Qualifier("server1BasicAuthClient")
@CitrusEndpoint
private HttpClient server1BasicAuthClient;

@Autowired
@Qualifier("server2BasicAuthClient")
@CitrusEndpoint
private HttpClient server2BasicAuthClient;
....
}

Any ideas where and how to fix the issue ?

Thanks in advance.


Solution

  • If you intend to express annotation-driven injection by name, do not primarily use @Autowired, even if is technically capable of referring to a bean name through @Qualifier values. Instead, use the JSR-250 @Resource annotation, which is semantically defined to identify a specific target component by its unique name, with the declared type being irrelevant for the matching process.

    As a specific consequence of this semantic difference, beans that are themselves defined as a collection or map type cannot be injected through @Autowired, because type matching is not properly applicable to them. Use @Resource for such beans, referring to the specific collection or map bean by unique name.

    @Autowired applies to fields, constructors, and multi-argument methods, allowing for narrowing through qualifier annotations at the parameter level. By contrast, @Resource is supported only for fields and bean property setter methods with a single argument. As a consequence, stick with qualifiers if your injection target is a constructor or a multi-argument method.


    Try to set using value instead of name OR use @Primary

    @Bean(value="server1BasicAuthClient")
    @Bean(value="server2BasicAuthClient")
    

    Refer 1 Refer 2