satish marathe
satish marathe

Reputation: 1133

Springs @Qualifier annotation not working

Am playing around with @Qualifier along with @Autowired.
Here is my application context file

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

<bean id="helloBean" class="com.springex1.HelloWorld1">
    <property name="name" value="Mkyong" />
</bean>

<bean id="address1" class="com.springex1.Address" >
    <property name="street" value="sahajanand" />
</bean>

<bean id="address2" class="com.springex1.Address" >
    <property name="street" value="pune" />
</bean>

Here are my Java classes
HelloWorld1.java

package com.springex1;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

public class HelloWorld1 {
private String name;

@Autowired
@Qualifier("address1")
private Address address = null; 

public void setName(String name) {
    this.name = name;
}


public void setAddress(Address address) {
    this.address = address;
}

public void printHelloWithAddress() {
    System.out.println("Hello ! " + name + " your street " + address.getStreet());
}


}

Address.java

package com.springex1;

public class Address {
private String street = "";

public void setStreet(String street) {
    this.street = street;
}

public String getStreet(){
    return this.street;
}
}

Here is where I am trying to get things to run - App.java

package com.springex1;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {

public static void main(String[] args) {

    call1("appContext1.xml");           
}

public static void call1(String appContext){
    ApplicationContext context = new ClassPathXmlApplicationContext(appContext);

    HelloWorld1 obj = (HelloWorld1) context.getBean("helloBean");
    obj.printHelloWithAddress();
}     
} 

I keep getting this exception -ideally I should not since I have the @Qualifier annotation with the id 'address1' defined - so it should not throw an exception

WARNING: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloBean': Unsatisfied dependency expressed through field 'address': No qualifying bean of type [com.springex1.Address] is defined: expected single matching bean but found 2: address1,address2; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.springex1.Address] is defined: expected single matching bean but found 2: address1,address2 Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'helloBean': Unsatisfied dependency expressed through field 'address': No qualifying bean of type [com.springex1.Address] is defined: expected single matching bean but found 2: address1,address2; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [com.springex1.Address] is defined: expected single matching bean but found 2: address1,address2 at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)

I am using spring 4.3 release version - this is the only dependency in my pom

    <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>4.3.0.RELEASE</version>
</dependency>
<!-- 
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>4.3.0.RELEASE</version>
</dependency>
 -->

Upvotes: 1

Views: 3432

Answers (3)

Headake
Headake

Reputation: 33

Spring 4.x uses the following bean schema:

<beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

You also need to add:

<context:annotation-config /> 

or:

<context:component-scan base-package="com.test.package" />

By adding one of these tags you can remove the AutowiredAnnotationBeanPostProcessor definition from the xml.

Upvotes: 0

Moshe Arad
Moshe Arad

Reputation: 3733

First, it is recommended by Spring docs not to use the @Qualifier and instead of it's recommended to use the @Resource annotation which do its injecting by name (like a qualifier).

So option one is to replace the @Qualifier with @Resource annotation.

But in order IOC will do its injecting properly using @Resource you should

name Address address to Address address1

Now, if you still want to use @Qualifier you'll have to change your configuration to:

<bean id="address1" class="com.springex1.Address" >
    <property name="street" value="sahajanand" />
    <qualifier value="address1"/>
</bean>

Upvotes: 1

Vasu
Vasu

Reputation: 22442

You need to add <context:annotation-config /> to the configuration xml to resolve the @Qualifier annotation, you can find the updated xml below:

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<context:annotation-config />

<bean class="org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor" />

<bean id="helloBean" class="com.code.samples.HelloWorld1">
    <property name="name" value="Mkyong" />
</bean>

<bean id="address1" class="com.code.samples.Address" >
    <property name="street" value="sahajanand" />
</bean>

<bean id="address2" class="com.code.samples.Address" >
    <property name="street" value="pune" />
</bean>
</beans>

Upvotes: 1

Related Questions