6

I am getting the following error when trying to autowire two beans using

No qualifying bean of type [javax.jms.ConnectionFactory] is defined: expected single matching bean but found 2: aConnectionFactory, bConnectionFactory

Description:

Parameter 1 of method jmsListenerContainerFactory in org.springframework.boot.autoconfigure.jms.JmsAnnotationDrivenConfiguration required a single bean, but 2 were found:
        - aConnectionFactory: defined by method 'aConnectionFactory' in package.Application
        - bConnectionFactory: defined by method 'bConnectionFactory' in package.Application


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

I have this annotation driven configuration:

@SpringBootApplication
@EnableIntegration
@IntegrationComponentScan
public class Application  extends SpringBootServletInitializer implements
 WebApplicationInitializer {

    @Resource(name = "aConnectionFactory")
    private ConnectionFactory aConnectionFactory;

    @Resource(name = "bConnectionFactory")
    private ConnectionFactory bConnectionFactory;

    @Bean
    public IntegrationFlow jmsInboundFlow() {
        return IntegrationFlows
                    .from(
                        Jms.inboundAdapter(aConnectionFactory)
                                            .destination(aQueue),
                        e -> e.poller( Pollers.fixedRate(100, 
TimeUnit.MILLISECONDS).maxMessagesPerPoll(100))
                     ).channel("entrypoint")
                     .get();
}

   @Bean
    public IntegrationFlow jmsInboundFlowB() {
        return IntegrationFlows
                    .from(
                        Jms.inboundAdapter(bConnectionFactory)
                                            .destination(bQueue),
                        e -> e.poller( Pollers.fixedRate(100, 
TimeUnit.MILLISECONDS).maxMessagesPerPoll(100))
                     ).channel("entrypoint")
                     .get();
}


    @Bean(name = "aConnectionFactory")
    @Profile({"weblogic"})
    public ConnectionFactory aConnectionFactory() {
        ConnectionFactory factory = null;
        JndiTemplate jndi = new JndiTemplate();
        try {
          factory = (ConnectionFactory) jndi.lookup("jms/ConnectionFactory");
        } catch (NamingException e) {
            logger.error("NamingException for jms/ConnectionFactory", e);
        }

        return factory;
    }

    @Bean(name = "bConnectionFactory")
    @Profile({"weblogic"})
    public ConnectionFactory bConnectionFactory() {
        ConnectionFactory factory = null;
        JndiTemplate jndi = new JndiTemplate();
        try {
          factory = (ConnectionFactory) jndi.lookup("jms/ConnectionFactory");
        } catch (NamingException e) {
            logger.error("NamingException for jms/ConnectionFactory", e);
        }

        return factory;
    }

}

Any ideas what's wrong in this code? This seems to be straight forward, but specifying the Qualifier doesn't work, I have also tried to use @Resource. What am I missing there?

Any help appreciated.

karruma
  • 768
  • 1
  • 12
  • 32
  • spring confuses between your @Resource(name = "aConnectionFactory") and @Bean(name = "aConnectionFactory"). As console suggest you need to mark one them as primary (same for bConnectionFactory ) – kuhajeyan Nov 07 '16 at 17:53

2 Answers2

9

Nothing wrong with your code.

That is just JmsAnnotationDrivenConfiguration from Spring Boot which doesn't like your two ConnectionFactory beans, but requires only one.

  1. Why just don't follow with that report recommendations and mark one of them with the @Primary?

  2. Looks like you don't use Spring Boot JMS auto-configuration feature, so that would be just straightforward to disable JmsAnnotationDrivenConfiguration: http://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/reference/htmlsingle/#using-boot-disabling-specific-auto-configuration

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
  • Thanks Artem, I can't mark any of them as @Primary as I need two of them to be autowired to define two different jmsInboudFlows (from different queues using different connection factories). – karruma Nov 07 '16 at 18:00
  • That's correct, but you can use `@Autowired` together with `@Qualifier`. But anyway, I guess, it would be better for you ti disable `JmsAnnotationDrivenConfiguration` since you fully don't use its functionality. – Artem Bilan Nov 07 '16 at 18:03
  • Note that in order to disable it in the latest versions of Spring Boot, you need to exclude JmsAutoConfiguration as JmsAnnotationDrivenConfiguration is not public. – Vlad Schnakovszki Jun 20 '19 at 16:50
-1

The problem consist

javax.jms.ConnectionFactory is singleton, you need one object that type!

Solutions for your problem:

  • If you need two object that create objects and extend ConnectionFactory them change scope as needed.
  • try @Scope("singleton") or @Scope("prototype").
  • if you receive error, make a objects. then use a scope @Scope("singleton")
  • "Other Two" disfigure the other class that is already using and setting such an.
Marcelo Ferreira
  • 428
  • 1
  • 5
  • 20
  • Not sure what you're suggesting - what I need is two singletons of the same type, and as far as I know I can have two singleton beans of the same. What I am looking for is to autowire the correct one. – karruma Nov 07 '16 at 17:50
  • that is correct, find that implement interface or class, there somewhere in your project, see the wrong is clean. try define scope that @Scope("prototype"), for your two beas – Marcelo Ferreira Nov 07 '16 at 17:56
  • This does not address the question - the problem is not with scopes here - there is nothing wrong with the code. Please see the accepted answer and the comments below it, which give the correct solution to the question. – wavicle Nov 17 '20 at 22:16