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

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/><beanid="triangle"class="com.hubberspot.spring.qualifier.Triangle"></bean><beanid="side1"class="com.hubberspot.spring.qualifier.Side"><propertyname="length"value="5"></property><propertyname="pointX"value="2"></property><propertyname="pointY"value="3"></property></bean><beanid="side2"class="com.hubberspot.spring.qualifier.Side"><propertyname="length"value="7"></property><propertyname="pointX"value="5"></property><propertyname="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 :

Program to demonstrate how to turn on Auto Scanning of Spring Components for automatic scanning, detecting and instantiating the beans

Spring Framework container uses Spring Configuration XML file for scanning , detecting and instantiating of beans / components. Spring Framework now provides us a way to automate this whole process of dealing with beans. Instead of dealing with beans and components manually, now we can ask Spring container to scan into a particular package and see if there are any classes with specific annotations for getting registered as a bean. By-default Auto Scanning of beans is turned off.

In order to turn on Auto Scanning we need to provide an entry in Spring Configuration file. The entry is just a tag with name "context:component-scan". As soon as we provide Spring this tag, it gets capabilities of automatically discovering and declaring beans.

This tag is very much similar to the tag "context:annotation-config". The only difference between the two is that "context:annotation-config" does not scans the beans in package.

Tag "context:component-scan" scans package and all its sub-packages for classes having specific annotations such as @Component , @Service etc to register that class as a Spring bean. This tag comes up with a attribute called as base-package, which tells the container from where it has to start scanning.

There are usually four major annotations for which the "context:component-scan" tag scans :

1. @Component - This annotation tells "context:component-scan" tag that its a class which can be treated as Spring Component.

2. @Service - This annotation tells "context:component-scan" tag that its a class which can be treated as Service.

3. @Repository - This annotation tells "context:component-scan" tag that its a class which can be treated as data repository.

4. @Controller - This annotation tells "context:component-scan" tag that its a class which can be treated as Controller for Spring Model-View-Controller.

How to provide entry for "context:component-scan" tag in Spring Configuration File ?

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 Auto Scanning in Spring we need to provide a tag
by name <context:component-scan> see the tag below .... --><context:component-scanbase-package="com.hubberspot.spring.components"/></beans>

Above XML contains an entry for "context:component-scan" which makes Spring container detect, scan and instantiate bean automatically. By above example, the container looks in the package com.hubberspot.components and all its sub-packages for the classes having specific components declared above.

A simple snippet showing how to turn on Annotations in Spring Configuration file

Annotations came into picture with JDK 1.5 to make life of a developer easier. Annotations are meta-data which provides additional information about something. It is applied to various variables , methods , classes , constructors and other declarations. Spring provides annotations as an alternative way over xml based configuration.

Annotations are turned off by-default by Spring Framework. In order to turn it on we have to provide a entry in Spring Configuration file. Using tag context:annotation-config from Spring's context namespace makes it turn on. Annotation makes development easier and faster. It also takes addition of information closer to source code. Annotation injection is done prior to xml based injection by Spring Framework.

<?xmlversion="1.0"encoding="UTF-8"?><beansxmlns="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/><beanid="employee"class="com.hubberspot.spring.autowire.Employee"<propertyname="name"value="Jonty"/><propertyname="age"value="28"/><propertyname="address"ref="address"></property></bean><beanid="address"class="com.hubberspot.spring.autowire.Address"><propertyname="street"value="Town Hall Street"/><propertyname="city"value="Pune"/><propertyname="state"value="Maharashtra"></property></bean></beans>

After the annotations in Spring file is turned on, Spring automatically wires many components such as properties , constructors and various stuff to a value.

package com.hubberspot.code;
import java.util.Scanner;
public class SquareAndCubeRootdemo {
public static void main(String[] args) {
// Create a Scanner object which will read
// values from the console which user enters
Scanner scanner = new Scanner(System.in);
// Getting input from user from the console
System.out.println("Enter value of number for which you want Square root ");
// Calling nextDouble method of scanner for
// taking a double value from user and storing
// it in number variable
double number = scanner.nextDouble();
System.out.println();
System.out.println("Calculating Square root of a number ... ");
// In order to calculate Square root of a number
// we use Math class Math.sqrt() static method which takes in a
// number and returns back the square root of that number
double result = Math.sqrt(number);
// printing the result on the console
System.out.println("Square root of " + number + " is : " + result);
System.out.println();
// Getting input from user from the console
System.out.println("Enter value of number for which you want Cube root ");
// Calling nextDouble method of scanner for
// taking a double value from user and storing
// it in number variable
number = scanner.nextDouble();
System.out.println();
System.out.println("Calculating Cube root of a number ... ");
// In order to calculate Cube root of a number
// we use Math class Math.cbrt() static method which takes in a
// number and returns back the square root of that number
result = Math.cbrt(number);
// printing the result on the console
System.out.println("Cube root of " + number + " is : " + result);
}
}

Program to demonstrate how to use InitializingBean and DisposableBean interface for initializing and destroying a bean in Spring Framework

Step 1 - Create a POJO class here its Employee.java having getters, setters, constructor and implementing two interfaces InitializingBean and DisposableBean, along with its unimplemented methods as afterPropertiesSet() and destroy()

package com.hubberspot.spring.InitDestroy;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
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.
AbstractApplicationContext context =
new ClassPathXmlApplicationContext(("spring.xml"));
// Using AbstractApplicationContext registerShutdownHook()
// method to demonstrate destroy() method being called
context.registerShutdownHook();
// 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 Employee object. Without implementing new keyword we
// have injected object of Employee just by reading an xml
// configuration file.
Employee employee = (Employee)context.getBean("employee");
System.out.println("The name of Employee is : " + employee.getName());
System.out.println("The age of Employee is : " + employee.getAge());
}
}