@Qualifier Annotation in Spring is not working
Asked Answered
T

5

7

I have just learnt Spring Framework and have been using Spring 2.5 for this learning. I have created three beans with these classes

Food.java

package com.spring.danipetrick;

public interface Food {
    void ingredients(); 
}

NasiGoreng.java

package com.spring.danipetrick;

public class NasiGoreng implements Food {

    public NasiGoreng() {

    }

    public void ingredients() {
        System.out.println("Rice, Coconut oil, Egg, Crackers");
    }

    @Override
    public String toString() {
        return "Nasi Goreng";
    }
}

Rendang.java

package com.spring.danipetrick;

public class Rendang implements Food {
    public void ingredients() {
        System.out.println("Beef, Coconut milk, spices");
    }

    @Override
    public String toString() {
        return "Rendang";
    }
}

PecintaKuliner.java

package com.spring.danipetrick;

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

public class PecintaKuliner {

    @Autowired
    @Qualifier("nasigoreng")
    private Food food;

    @Autowired
    public void setFood(Food food) {
        this.food = food;
    }

    public Food getFood() {
        return this.food;
    }

    public void sayMaknyus() {
        System.out.println(food.toString() + " memang maknyus...");
    }
}

Xml configuration, qualifier-test.xml

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
     http://www.springframework.org/schema/context 
     http://www.springframework.org/schema/context/spring-context.xsd">

  <context:annotation-config />

  <bean id="bondan" class="com.spring.danipetrick.PecintaKuliner">
  </bean>

  <bean id="rendang" class="com.spring.danipetrick.Rendang"/>

  <bean id="nasigoreng" class="com.spring.danipetrick.NasiGoreng" />

</beans>

Finally, class with main method is QualifierTestMain.java:

package com.spring.danipetrick;

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

public class QualifierTestMain {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("/qualifier-test.xml"); 

        PencintaKuliner bondan = (PencintaKuliner)context.getBean("bondan");
        bondan.sayMaknyus();
    }
}

When I run this project, I have an error like this

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No unique bean of type [com.spring.danipetrick.Food] is defined: expected single matching bean but found 2: [rendang, nasigoreng]

Why @Qualifier annotation is not working in my case?

Turgid answered 23/11, 2013 at 6:7 Comment(1)
I had a similar problem injecting twice the dependency in a Service by the constructor (AllArgsConstructor by lombok) and field.Dawson
T
3

Try only removing @Autowired from setFood() in PecintaKuliner

like

@Autowired
@Qualifier("nasigoreng")
private Food food;

public void setFood(Food food) {
    this.food = food;
}
Triplenerved answered 23/11, 2013 at 6:39 Comment(3)
Hey this is working. Can you tell me how it works? Thanks Sandhu :)Turgid
You can't use annotations on both setter and fields at the same time. Either use it with fields or with setter.Triplenerved
@Sandhu Technically you can. It's just redundant.Xenomorphic
X
9

Both your method and field are annotated with @Autowired. As such, Spring will try to inject both. On one of the runs, it will try to inject

@Autowired
@Qualifier("nasigoreng")
private Food food;

which will work because the injection target is qualified.

The method however

@Autowired
public void setFood(Food food) {
    this.food = food;
}

does not qualify the injection parameter so Spring doesn't know which bean to inject.

Change the above to

@Autowired
public void setFood(@Qualifier("nasigoreng") Food food) {
    this.food = food;
}

But you should decide one or the other, field or setter injection, otherwise it is redundant and may cause errors.

Xenomorphic answered 23/11, 2013 at 6:13 Comment(0)
R
4

I tried with Spring 4.2.4. Problem resolved just by adding <context:annotation-config /> in configuration file.

Regurgitate answered 19/1, 2016 at 17:40 Comment(0)
T
3

Try only removing @Autowired from setFood() in PecintaKuliner

like

@Autowired
@Qualifier("nasigoreng")
private Food food;

public void setFood(Food food) {
    this.food = food;
}
Triplenerved answered 23/11, 2013 at 6:39 Comment(3)
Hey this is working. Can you tell me how it works? Thanks Sandhu :)Turgid
You can't use annotations on both setter and fields at the same time. Either use it with fields or with setter.Triplenerved
@Sandhu Technically you can. It's just redundant.Xenomorphic
A
2

Try removing you constructor from the NasiGoreng class. It worked for me.

Americanize answered 20/5, 2020 at 16:42 Comment(1)
Yes it worked!!! But I didn't understand why constructor would cause a problem?Breena
C
1

For others facing issue in Spring 5 -- Use xmlns based configuration..

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
    <context:annotation-config/>

</beans>
Christian answered 13/5, 2022 at 9:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.