Reputation: 183
I am trying to implement factory pattern to get producer from a list of available ones. While doing it i am getting the below exception. Not able to figure out the issue with the code. Can you please let me know what i am missing.
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.test.interfaces.Producer] is defined: expected single matching bean but found 2: A,B
Please find the code below
public interface Producer<T> {
public void start();
public List<T> produce() throws CEHServiceException;
public void stop();
}
@Component("A")
public class ProducerA extends Producer {
//Autowire Services & Properties
}
@Component("B")
public class ProducerB extends Producer {
//Autowire Services & Properties
}
@Configuration
public class AgentConfiguration {
@Bean
public ServiceLocatorFactoryBean createProducerFactoryBean(){
ServiceLocatorFactoryBean bean = new ServiceLocatorFactoryBean();
bean.setServiceLocatorInterface(ProducerFactory.class);
return bean;
}
}
public interface ProducerFactory {
Producer getProducer(String producerName);
}
@Component
public class AdvancedAgentProcessor {
@Autowired
private ObjectFactory<AdvancedRunnerImpl> runnerFactory;
public void init(){
AdvancedRunnerImpl runner = runnerFactory.getObject();
runner.setProducerName("A");
runner.start();
}
}
@Component
@Scope("prototype")
public class AdvancedRunnerImpl implements Runner {
@Autowired private ProducerFactory producerFactory;
private Producer producer;
private String producerName;
public void start() {
producer = producerFactory.getProducer(this.producerName);
}
}
Full stack tracke
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.test.etl.interfaces.Producer] is defined: expected single matching bean but found 2: A,B
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:365)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
at org.springframework.beans.factory.config.ServiceLocatorFactoryBean$ServiceLocatorInvocationHandler.invokeServiceLocatorMethod(ServiceLocatorFactoryBean.java:377)
at org.springframework.beans.factory.config.ServiceLocatorFactoryBean$ServiceLocatorInvocationHandler.invoke(ServiceLocatorFactoryBean.java:363)
at com.sun.proxy.$Proxy34.getProducer(Unknown Source)
at com.test.runner.AdvancedRunnerImpl.start(AdvancedRunnerImpl.java:54)
at com.test.app.AdvancedAgentProcessor.init(AdvancedAgentProcessor.java:48)
at com.test.app.DataAgentApplication.main(DataAgentApplication.java:25)
Upvotes: 1
Views: 5115
Reputation: 11655
Spring does not know which component to autowire. It seems that the problem is in the ProducerFactoryImplementation but we cannot see it.
There are three possible solutions:
Use Qualifiers so you can tell Spring which specific implementation you want.There is an example in StackOverflow here
Use the Primary annotation (See more here3). That means that in case of ambiguity Spring will give priority to the @Primary annotated component
Autowire a list of beans. Something like:
@Autowired private List<Producer> myAvalilableProducers;
public Producer getByName(name){
for( Producer producer: myAvalilableProducers){
if(producer.getName().equals(name)){ return producer; }
}
throw new RuntimeException("No producer with name " + name " found");
}
This third option more useful when you do not know the specific instance at compile time or if you really want to inject a list of components.
Upvotes: 2
Reputation: 1
This happens when the dynamic proxy is not able to pick the correct Bean. Please check whether this.producerName
is null or empty.
Upvotes: 0
Reputation: 48694
You have two beans that extend Producer. Somewhere you are trying to autowire a Producer. Spring does not know which Producer to use.
Upvotes: 0