Spring Annotation using @Qualifier

In this previous article, we have seen an example demonstrating how annotation can be used to inject dependencies. @Autowired annotation injects dependencies using byType and this could be problem when we got two beans with same data type & throws ‘NoUniqueBeanDefinitionException’ exception as we seen in the byType<link> example.

The solution to above problem is, in addition to the @Autowired annotation we must include one more annotation called @Qualifier(“beanName”) to make aware the container as to which one of the two beans needs to be injected at the runtime.

Note: If there are two beans of same data type named ‘address’ & ‘addressB’ defined in the configuration file, then in this case spring container injects the first bean ‘address’ bean by default. This is because, container lowercase the first character of the collaborating bean.

For example,

if the dependent property is Address then it lowercase the first character and make it ‘address’ and injects it.

We will extend the same example used for @Autowired annotation

Technology Used

  • Java 1.7
  • Eclipse Kepler
  • Maven 3.0.4
  • Spring-4.0.0-RELEASE

Mavenize or download required jars

Add Spring-4.0.0 dependencies to the pom.xml

<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-core</artifactId>
	<version>${spring.version}</version>
</dependency>
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-context</artifactId>
	<version>${spring.version}</version>
</dependency>

Folks who aren’t familiar with Maven concepts or don’t require maven for their project, can download the below jars individually from the spring site and include them in the classpath.

  • spring-core-4.0.0-RELEASE
  • spring-context-4.0.0-RELEASE
  • spring-beans-4.0.0-RELEASE
  • spring-aop-4.0.0-RELEASE
  • spring-expression-4.0.0-RELEASE
  • commons-logging-1.1.1
  • aopalliance-1.0

Let’s see coding in action

 

Create simple Spring bean for Employee & Address

Address class

Four simple properties with their setter/getter

Address.java

package com.spring.series.annotation;

public class Address {

	private String street;
	private String city;
	private String state;
	private String zipcode;

	/**
	 * getter's and setter's
	 */
	public String getStreet() {
		return street;
	}
	public void setStreet(String street) {
		this.street = street;
	}
	public String getCity() {
		return city;
	}
	public void setCity(String city) {
		this.city = city;
	}
	public String getState() {
		return state;
	}
	public void setState(String state) {
		this.state = state;
	}
	public String getZipcode() {
		return zipcode;
	}
	public void setZipcode(String zipcode) {
		this.zipcode = zipcode;
	}

	/**
	 * This method prints the address details
	 */
	public void printAddressDetail(){
		System.out.println("Address Street \t\t: " + street);
		System.out.println("Address City \t\t: " + city);
		System.out.println("Address State \t\t: " + state);
		System.out.println("Address Zip Code \t: " + zipcode);
	}
}

Employee class

Four simple properties and its setter/getter & one complex property named Address annotated with @Autowired and @Qualifier to inform the IOC container as to which bean needs to be injected.

Note: When we declared @Autowired, actually it autowire byType. There is one more annotation in Spring called @Resource annotation which autowires using byname

Employee.java

package com.spring.series.annotation;

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

public class Employee {

	private String name;
	private int age;
	private String employeeCode;
	private String designation;

	// property address autowired using annotation
	@Autowired
    @Qualifier("addressB")
	private Address address;

	/**
	 * getter's and setter's
	 */
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public String getEmployeeCode() {
		return employeeCode;
	}
	public void setEmployeeCode(String employeeCode) {
		this.employeeCode = employeeCode;
	}
	public String getDesignation() {
		return designation;
	}
	public void setDesignation(String designation) {
		this.designation = designation;
	}
	public Address getAddress() {
		return address;
	}
	public void setAddress(Address address) {
		this.address = address;
	}

	/**
	 * This method prints the employee details
	 */
	public void printEmployeeDetail(){

		System.out.println("Employee Name \t\t: " + name);
		System.out.println("Employee Age \t\t: " + age);
		System.out.println("Employee Code \t\t: " + employeeCode);
		System.out.println("Employee Designation \t: " + designation);

		System.out.println("\nAutowired Address object & Printing Address details\n");

		// this loc invokes method of Address class & this object is injected during spring bean instantiation
		address.printAddressDetail();
	}
}

Create Spring Bean Configuration file (Spring XML)

Two simple beans employee & address are defined in the Spring configuration file with no explicit relationship between them because dependent address bean gets injected into the employee via @Autowired annotation declared in the component class (i.e.; Employee.java)

<?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-4.0.xsd">

	<context:annotation-config />

	<!-- employee bean definition goes here -->
	<bean id="employee" class="com.spring.series.annotation.Employee">
		<property name="name" value="Mark" />
		<property name="age" value="32" />
		<property name="employeeCode" value="E10910" />
		<property name="designation" value="Software Architect" />
	</bean>

	<!-- address bean definition goes here -->
	<bean id="addressA" class="com.spring.series.annotation.Address">
		<property name="street" value="Spring Office St." />
		<property name="city" value="Columbus" />
		<property name="state" value="OHIO" />
		<property name="zipcode" value="43211" />
	</bean>

	<!-- address bean definition goes here -->
	<bean id="addressB" class="com.spring.series.annotation.Address">
		<property name="street" value="Spring Office St. B" />
		<property name="city" value="Columbus B" />
		<property name="state" value="OHIO B" />
		<property name="zipcode" value="43211 B" />
	</bean>

</beans>

Note: Name of the Spring Bean Configuration file can be anything (not necessary to have SpringContext.xml) and it’s your choice. But, in the enterprise application keep these file names appropriate to the business context. So that it will increase the readability of the application.

Project Structure in Eclipse (Package Explorer view)

SpringAnnotationQualifier

Test the Application that’s exactly …. Run it!

Let’s test using ApplicationContext

Simple test class – self descriptive

TestEmployee.java

package com.spring.series.annotation;

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

public class TestEmployee {

	public static void main(String[] args) {
		testAnnotation();
	}

	private static void testAnnotation(){

		ApplicationContext applicationContext = new ClassPathXmlApplicationContext("com/spring/series/annotation/SpringContext.xml");
		Employee employee = (Employee) applicationContext.getBean("employee");

		System.out.println("\nSpring Annoatation with @Qualifer & @Autowired \n");

		// invoke print() method of Employee class
		employee.printEmployeeDetail();
	}
}

Output in console

Spring Annoatation with @Qualifer & @Autowired 

Employee Name 		: Mark
Employee Age 		: 32
Employee Code 		: E10910
Employee Designation 	: Software Architect

Autowired Address object & Printing Address details

Address Street 		: Spring Office St. B
Address City 		: Columbus B
Address State 		: OHIO B
Address Zip Code 	: 43211 B

In the next article, we will implement an example for @Resource annotation similar to byName autowiring mode

Download project

Spring Annotation using @Qualifier (3kB)

Happy Coding!!
Happy Learning!!