Spring Annotation using @Required

In this article, we will learn to enforce the spring container to inject certain properties into the bean otherwise asking to throw an error. With @Required annotation, container makes sure that certain property(properties) are injected into the bean

Technology Used

  • Java 1.7
  • Eclipse Kepler IDE
  • 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

Employee class

Four simple properties and its setter/getter. And setter methods of ‘name’ & employeeCode’ are annotated with @Required annotation. This additional annotation enforces the spring container to injects these property values into the bean, otherwise raising a ‘BeanInitializationException’ exception.

Note: setter method of properties ‘name’ & ‘employeeCode’ are annotated with @Required annotation

Employee.java

package com.spring.series.annotation;

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

public class Employee {

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

	/**
	 * getter's and setter's
	 */
	public String getName() {
		return name;
	}
	@Required
	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;
	}
	@Required
	public void setEmployeeCode(String employeeCode) {
		this.employeeCode = employeeCode;
	}
	public String getDesignation() {
		return designation;
	}
	public void setDesignation(String designation) {
		this.designation = designation;
	}

	/**
	 * 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);
	}
}

Create Spring Bean Configuration file (Spring XML)

Pretty straightforward as seen in the previous examples, a bean defined in the Spring XML Configuration. Deliberately, commented out its two properties i.e.; ‘name’ & ‘employeeCode’ to see how container behaves having @Required annotation in the component class and not providing their values in the Spring configuration XML

Note: Later we will un-comment to see what container do this time

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

	<!-- this tags turns ON annotation in the registered bean component classes -->
	<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>

</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)

SpringAnnotationRequired

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 @Required \n");

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

Output in console

Aug 03, 2014 4:48:12 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@7c39aa6: startup date [Sun Aug 03 16:48:12 IST 2014]; root of context hierarchy
Aug 03, 2014 4:48:12 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [com/spring/series/annotation/SpringContext.xml]
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'employee' defined in class path resource [com/spring/series/annotation/SpringContext.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Properties 'employeeCode' and 'name' are required for bean 'employee'
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:547)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
	at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:304)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:300)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:195)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:700)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:760)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
	at com.spring.series.annotation.TestEmployee.testAnnotation(TestEmployee.java:14)
	at com.spring.series.annotation.TestEmployee.main(TestEmployee.java:9)
Caused by: org.springframework.beans.factory.BeanInitializationException: Properties 'employeeCode' and 'name' are required for bean 'employee'
	at org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.postProcessPropertyValues(RequiredAnnotationBeanPostProcessor.java:156)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1185)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:537)
	... 12 more

From the console output, it is quite evident that having @Required annotation in the component and not supplying their values will make the container to throw ‘BeanInitializationException’ exception.

Let’s uncomment the two properties which were commented out earlier and see what container does ?

Output in console after un-commenting the two properties

Spring Annoatation with @Required 

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

Conclusion: With @Required annotation set, its the developer’s responsibility to make sure those dependencies are supplied. Otherwise ending up reading those dirty error trace in the console log

Download project

Spring Annotation using @Required (3kB)

Happy Coding !!
Happy Learning !!

Spring Bean Lifecycle
Spring Annotation using @Resource