Free Data Structures and Algorithms Course









Subscribe below and get all best seller courses for free !!!










OR



Subscribe to all free courses

How to use @Qualifier annotation in Spring Framework in making bean qualify to auto-wire from multiple beans ?.

Program to demonstrate how to use @Qualifier annotation in Spring Framework in making bean qualify from multiple beans

When it comes to Auto-wiring there can arise a case when there are two or more beans which qualifies to be autowired to a property. In such a scenario, Spring cannot decide that which bean it needs to autowire to. If it fails in deciding, it throws a exception as "org.springframework.beans.factory.NoSuchBeanDefinitionException". See the problem scenario code below :

1. A normal POJO class Side.java having three properties length, pointX and pointY

package com.hubberspot.spring.qualifier;

public class Side {

 private int length;
 private int pointX;
 private int pointY;


 public int getLength() {
  return length;
 }

 public void setLength(int length) {
  this.length = length;
 }

 public int getPointX() {
  return pointX;
 }

 public void setPointX(int pointX) {
  this.pointX = pointX;
 }


 public int getPointY() {
  return pointY;
 }

 public void setPointY(int pointY) {
  this.pointY = pointY;
 }

}




2. A normal POJO class Triangle.java having Side as property which is auto-wired using @Autowired annotation

package com.hubberspot.spring.qualifier;

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

public class Triangle {

 private Side side;


 public Side getSide() {
  return side;
 }

 @Autowired 
 public void setSide(Side side) {
  this.side = side;
 }

}




3. Spring Configuration XML file having bean declaration for one Triangle class and Two Side class


1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.

<?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-3.1.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <!-- In order to turn on Annotations in Spring over xml configuration we 
        need to provide a tag by name <context:annotation-config> see the tag below 
        .... -->

    <context:annotation-config />

    <bean id="triangle" class="com.hubberspot.spring.qualifier.Triangle">

    </bean>

    <bean id="side1" class="com.hubberspot.spring.qualifier.Side">
        <property name="length" value="5"></property>
        <property name="pointX" value="2"></property>
        <property name="pointY" value="3"></property>
    </bean>

    <bean id="side2" class="com.hubberspot.spring.qualifier.Side">
        <property name="length" value="7"></property>
        <property name="pointX" value="5"></property>
        <property name="pointY" value="2"></property>
    </bean>


</beans>



4. Test class for running the program

package com.hubberspot.spring.autowire;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.hubberspot.spring.qualifier.Triangle;

public class Test {

 public static void main(String[] args) {

  // ApplicationContext is a Spring interface which 
  // provides with the configuration for an application. 
  // It provides us with all the methods that BeanFactory 
  // provides. It loads the file resources in a older 
  // and generic manner. It helps us to publish events to the
  // listener registered to it. It also provides quick support
  // for internationalization. It provides us with the object 
  // requested, it reads the configuration file and provides
  // us with the necessary object required.
  // We are using concrete implementation of ApplicationContext
  // here called as ClassPathXmlApplicationContext because this 
  // bean factory reads the xml file placed in the classpath of 
  // our application. We provide ClassPathXmlApplicationContext
  // with a configuration file called as spring.xml placed
  // at classpath of our application. 
  ApplicationContext context = 
    new ClassPathXmlApplicationContext(("spring.xml"));

  // In order to get a object instantiated for a particular bean 
  // we call getBean() method of ClassPathXmlApplicationContext
  // passing it the id for which the object is to be needed. 
  // Here getBean() returns an Object. We need to cast it back 
  // to the Triangle object. Without implementing new keyword we 
  // have injected object of Triangle just by reading an xml 
  // configuration file.
  Triangle triangle = (Triangle)context.getBean("triangle");

  System.out.println("The length of Triangle is : " + triangle.getSide().getLength());
  System.out.println("The x co-ordinate of Triangle is : " + triangle.getSide().getPointX());
  System.out.println("The y co-ordinate of Triangle is : " + triangle.getSide().getPointY());

 }

}



Note : When we run the Test class we get an exception trace which is shown below in the image.



Exception Occured on running Test Class :





Now, where is the problem with above code ?.

The problem lies in the Spring Configuration file where there are two beans of class Side. When Spring container finds that Triangle is been Auto-wired to Side class , it checks for Spring Configuration file to fulfill dependency. Here when Spring container scans XML file finds two beans with different id say "side1" and "side2" but of same type Side. It cannot decide which is the right bean developer is looking for. In order to overcome this problem we use @Qualifier annotation, which has value attribute where we set the id for which we need the bean auto-wiring. See the Triangle modified and right code below :


Right Scenario - Providing @Qualifier Annotation in Triangle Class


package com.hubberspot.spring.qualifier;

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

public class Triangle {

 private Side side;


 public Side getSide() {
  return side;
 }

 @Autowired
 @Qualifier("side1")
 public void setSide(Side side) {
  this.side = side;
 }

}




Output of the program after providing @Qualifier Annotation : 

 

 
© 2021 Learn Java by Examples Template by Hubberspot