Abhijeet Vaikar
Abhijeet Vaikar

Reputation: 1656

NoUniqueBeanDefinitionException when a parent and child class are components

I have a parent class

package com.org.pages.home;

@Component
public class HomePage extends BasePage {

}

I have a sub-class

package com.org.pages.home;

@Component
public class WebHomePage extends HomePage {

}

When I try to get an instance of HomePage in the following manner:

T page = applicationContext.getBean(registeredClass);
//Here registeredClass is of the type Class<T> and contains reference to com.org.pages.home.HomePage

It throws an exception:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.org.pages.home.HomePage' available: expected single matching bean but found 2: homePage,webHomePage

Questions
1. Why am I seeing this exception when I am clearly passing the class that I want to get a bean for?

2. How can I fix this? Please note that I cannot autowire these classes anywhere as there are around 40 of them, which is why I am instantiating them using

applicationContext.getBean();

Thanks for any help/suggestion!

Upvotes: 2

Views: 1382

Answers (2)

davidxxx
davidxxx

Reputation: 131436

You have two beans that are HomePage instances : homePage and webHomePage.
So Spring doesn't know which homePage instance you want as you invoke getBean(Class clazz) in this way ApplicationContext.getBean(HomePage.class).

Note that if you invoke ApplicationContext.getBean(WebHomePage.class), it would work as you have a single instance of WebHomePage.

As alternative with the programmatic way to retrieve the bean, you can use ApplicationContext.getBean(String name) by passing the bean name such as :

HomePage homePage = ApplicationContext.getBean("homePage")

Or :

HomePage homePage = ApplicationContext.getBean("webHomePage")

Please note that I cannot autowire these classes anywhere as there are around 40 of them, which is why I am instantiating them using

I don't really get why you could not use @@utowired. You should autowire the beans a the place where you need them.
Retrieving 40 beans in one shot will give too much responsibility to your method and to your class.

Upvotes: 0

Pankaj Singhal
Pankaj Singhal

Reputation: 16053

By Default, Spring framework automatically searches for matching bean. In case you have more than one bean for the same class(which includes the child classes) then you have to use

@Qualifier("beanName")

for matching by bean Name.

In your case, You can do the following:

@Component
@Qualifier("homePage")
public class HomePage extends BasePage {
}

and

@Component
@Qualifier("webHomePage")
public class WebHomePage extends HomePage {

}

Now you can use the following to get the HomePage bean:

HomePage page = (HomePage)applicationContext.getBean("homePage");

Upvotes: 1

Related Questions