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