Spring - Constructor Injection and arguments ambiguities

Posted on December 29, 2016


In this post we will learn how to resolve the ambiguities when bean attributes are injected via constructor injection.

Consider the following Employee bean class with attributes empId, name and age. There are two constructors in Employee bean class with same number of arguments.

Employee.java

package com.boraji.tutorial.spring;

public class Employee {
   private String name;
   private String empId;
   private int age;

   public Employee(String name, String empId, int age) {
      this.name = name;
      this.empId = empId;
      this.age = age;
      System.out.println("First Constructor");
   }

   public Employee(String name, int age, String empId) {
      this.name = name;
      this.age = age;
      this.empId = empId;
      System.out.println("Second Constructor");
   }

   public String getEmpId() {
      return empId;
   }

   public String getName() {
      return name;
   }

   public int getAge() {
      return age;
   }

}

Declared the Employee bean  in configuration metadata file.

beans.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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

	<bean id="employee" class="com.boraji.tutorial.spring.Employee">
		<constructor-arg value="John" />	<!-- Name -->
		<constructor-arg type="int" value="20" /> <!-- Age -->
		<constructor-arg value="1000" /> <!-- EmpId -->
	</bean>

</beans>

Create main class and run application.

MainApp.java

package com.boraji.tutorial.spring;

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

/**
 * @author imssbora
 */
public class MainApp {
   public static void main(String[] args) {
      @SuppressWarnings("resource")
      ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
      Employee employee = context.getBean("employee", Employee.class);
      System.out.println("Name : " + employee.getName());
      System.out.println("EmpId : " + employee.getEmpId());
      System.out.println("Age : " + employee.getAge());
   }
}

Output

First Constructor
Name : John
EmpId : 20
Age : 1000

The output is not as we expected, because Spring interprets the second and third argument of Employee constructor as string. To avoid this type of ambiguities we can specify the type of arguments by using type attribute of <constructor-arg/> element. 

 

Add type attribute in <constructor-arg/> element as shown below and run application.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

	<bean id="employee" class="com.boraji.tutorial.spring.Employee">
		<constructor-arg value="John" />	<!-- Name -->
		<constructor-arg type="int" value="20" /> <!-- Age -->
		<constructor-arg value="1000" /> <!-- EmpId -->
	</bean>

</beans>

Output

First Constructor
Name : John
EmpId : 1000
Age : 20

This time the output of our application is correct but the first constructor is called. To resolve this type of ambiguities we need to specify the constructor argument index in <constructor-arg/> element.

Now add index attribute in <constructor-arg/> element as shown below and run application.

<?xml version="1.0" encoding="UTF-8"?>
<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.xsd">

	<bean id="employee" class="com.boraji.tutorial.spring.Employee">
		<constructor-arg index="0" value="John" />	<!-- Name -->
		<constructor-arg index="1" type="int" value="20" /> <!-- Age -->
		<constructor-arg index="2" value="1000" /> <!-- EmpId -->
	</bean>

</beans>

Output

Second Constructor
Name : John
EmpId : 1000
Age : 20

Download this example from the below link and try the constructor injection and arguments ambiguities example

 

Download Sources