Beans

Spring Dependency Checking Example

This is an example of how to check dependencies in a Spring Bean. A Spring Bean can have dependencies of any type, such as primitive types, Collections or even Objects that are references to other beans. Sometimes it is necessary that specific dependencies have to be set, so that a Spring Bean is instantiated correctly.

Spring provides developers the ability to check if all mandatory dependencies of a Spring Bean have been set, either by using the @Required annotation or by defininig a custom @Required-style annotation by themselves. Furthermore, older Spring releases have offered developers the ability to check dependencies in different modes, via XML-configuration. This way is though deprecated now.

Let’s check a Spring Bean’s dependencies using all possible ways.

Our preferred development environment is Eclipse. We are using Eclipse Juno (4.2) version, along with Maven Integration plugin version 3.1.0. You can download Eclipse from here and Maven Plugin for Eclipse from here. The installation of Maven plugin for Eclipse is out of the scope of this tutorial and will not be discussed. We are also using Spring version 3.2.3 and the JDK 7_u_21.

Let’s begin.

1. Create a new Maven project

Go to File -> Project ->Maven -> Maven Project.

New-Maven-Project

In the “Select project name and location” page of the wizard, make sure that “Create a simple project (skip archetype selection)” option is checked, hit “Next” to continue with default values.

Maven-Project-Name-Location

In the “Enter an artifact id” page of the wizard, you can define the name and main package of your project. We will set the “Group Id” variable to "com.javacodegeeks.snippets.enterprise" and the “Artifact Id” variable to "springexample". The aforementioned selections compose the main project package as "com.javacodegeeks.snippets.enterprise.springexample" and the project name as "springexample". Hit “Finish” to exit the wizard and to create your project.

Configure-Maven-Project

The Maven project structure is shown below:

Maven-project-structure

    It consists of the following folders:

  • /src/main/java folder, that contains source files for the dynamic content of the application,
  • /src/test/java folder contains all source files for unit tests,
  • /src/main/resources folder contains configurations files,
  • /target folder contains the compiled and packaged deliverables,
  • the pom.xml is the project object model (POM) file. The single file that contains all project related configuration.

2. Add Spring 3.2.3 dependency

  • Locate the “Properties” section at the “Overview” page of the POM editor and perform the following changes:
    Create a new property with name org.springframework.version and value 3.2.3.RELEASE.
  • Navigate to the “Dependencies” page of the POM editor and create the following dependencies (you should fill the “GroupId”, “Artifact Id” and “Version” fields of the “Dependency Details” section at that page):
    Group Id : org.springframework Artifact Id : spring-web Version : ${org.springframework.version}

Alternatively, you can add the Spring dependencies in Maven’s pom.xml file, by directly editing it at the “Pom.xml” page of the POM editor, as shown below:
 
pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0"; xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.snippets.enterprise</groupId>
	<artifactId>springexample</artifactId>
	<version>0.0.1-SNAPSHOT</version>

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

	<properties>
		<spring.version>3.2.3.RELEASE</spring.version>
	</properties>
</project>

As you can see Maven manages library dependencies declaratively. A local repository is created (by default under {user_home}/.m2 folder) and all required libraries are downloaded and placed there from public repositories. Furthermore intra – library dependencies are automatically resolved and manipulated.

3. Check dependencies using the @Required annotation

The typical way to check a bean’s dependencies is the @Required annotation. It can be applied to setter methods of the bean properties that are mandatory for the bean instantiation.

Here, the employeeBean has a property that is annotated as @Required in its setter, so the bean cannot be created if this property is not set in the bean definition. Similarly, the personBean has a property that is reference to another bean and since it is also annotated as @Required in its setter the bean cannot be created if the reference bean is not set in its definition.
 
Employee.java

package com.javacodegeeks.snippets.enterprise.services;

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

public class Employee {
	
	private Long id;

	private String position;
	
	public Long getId() {
		return id;
	}

	@Required
	public void setId(Long id) {
		this.id = id;
	}
	
	public String getPosition() {
		return position;
	}

	public void setPosition(String position) {
		this.position = position;
	}
	
	@Override
	public String toString(){
		return "id "+ id + " and position " + position;
	}
}

 
Person.java

package com.javacodegeeks.snippets.enterprise.services;

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


public class Person {

	private String name;
	
	private Employee employee;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Employee getEmployee() {
		return employee;
	}

	@Required
	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	@Override 
	public String toString(){
		return "Person " + name + " is an employee, with " + employee + ".";
	}
}

In order that the @Required annotation is set correctly to check on Spring dependencies the RequiredAnnotationBeanPostProcessor has to be set. This class allows developers to annotate the setter properties of their own classes with annotations to indicate that the container must check for the configuration of a dependency injected value. The RequiredAnnotationBeanPostProcessor can be enabled in two ways.

One way is to include <context:annotation-config/> element in applicationContext.xml, as shown below:
 
applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

 <context:annotation-config />

	<bean id="personBean" class = "com.javacodegeeks.snippets.enterprise.services.Person">
		<property name="name" value="John"/>
		<property name="employee" ref="employeeBean"/>
	</bean>
	
		<bean id="employeeBean" class="com.javacodegeeks.snippets.enterprise.services.Employee">
		<property name="id" value="123"/>
		<property name="position" value="marketing"/>
	</bean>

</beans>

The other way is to define the RequiredAnnotationBeanPostProcessor as a bean in applicationContext.xml, as shown below:
 
applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

  <bean class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>

	<bean id="personBean" class = "com.javacodegeeks.snippets.enterprise.services.Person">
		<property name="name" value="John"/>
		<property name="employee" ref="employeeBean"/>
	</bean>
	
		<bean id="employeeBean" class="com.javacodegeeks.snippets.enterprise.services.Employee">
		<property name="id" value="123"/>
		<property name="position" value="marketing"/>
	</bean>

</beans>

4. Define a custom Required-style annotation for dependency checking

A second way to check the dependencies of a Spring bean is by creating a custom annotation of the same style as @Required annotation. The annotation will be equivalent to @Required annotation. Here, the @Mandatory interface is created.
 
Mandatory.java

package com.javacodegeeks.snippets.enterprise.interfaces;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
 
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Mandatory {

}

The @Mandatory annotation is applied in the employee property setter of Person bean to replace the @Required annotation.
 
Person.java

package com.javacodegeeks.snippets.enterprise.services;

import com.javacodegeeks.snippets.enterprise.interfaces.Mandatory;


public class Person {

	private String name;
	
	private Employee employee;

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Employee getEmployee() {
		return employee;
	}

	@Mandatory
	public void setEmployee(Employee employee) {
		this.employee = employee;
	}

	@Override 
	public String toString(){
		return "Person " + name + " is an employee, with " + employee + ".";
	}
}

The RequiredAnnotationBeanPostProcessor is necessary in this case too, so that the custom annotation is registered to Spring. In this case though, it needs a property, that is the new annotation to be registered. The property name is requiredAnnotationType and its value is set to the class path of the Mandatory interface.
 
applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd">

 <bean 
class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
	<property name="requiredAnnotationType" value="com.javacodegeeks.snippets.enterprise.interfaces.Mandatory"/>
</bean>
 
	<bean id="personBean" class = "com.javacodegeeks.snippets.enterprise.services.Person">
		<property name="name" value="John"/>
		<property name="employee" ref="employeeBean"/>
	</bean>
	
		<bean id="employeeBean" class="com.javacodegeeks.snippets.enterprise.services.Employee">
		<property name="id" value="123"/>
		<property name="position" value="marketing"/>
	</bean>

</beans>

5. Run the application

In both cases above, we can load the personBean and check what happens if its required dependency is missing. In App.class the bean is loaded and its toString() method is called to get its properties.
 
App.java

package com.javacodegeeks.snippets.enterprise;

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

import com.javacodegeeks.snippets.enterprise.services.Person;

public class App {
	
	@SuppressWarnings("resource")
	public static void main(String[] args) {
	
			ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
						
			Person person = (Person) context.getBean("personBean");
			
			System.out.println(person.toString());
	}
}

The result is shown below:

Person John is an employee, with id 123 and position marketing.

Now, if we remove the required employee property from personBean definition in applicationContext.xml and try to run the same application again, a BeanInitializationException will be thrown in both cases. The same exception will occur if we remove the id property from employeeBean definition.

6. Use check modes via XML – configuration (Spring 2.5 and older releases)

Another way that Spring older releases have provided to check beans’ dependencies was by using the dependency-check attribute inside the bean element in the bean definition. There were four different modes for the dependency check, as described below:
 
No dependency-check applicationContext.xml
The default mode, where no dependency check is performed.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-2.5.xsd">

	<bean id="personBean" class = "com.javacodegeeks.snippets.enterprise.services.Person">
		<property name="name" value="John"/>
		<property name="employee" ref="employeeBean"/>
	</bean>
	
		<bean id="employeeBean" class="com.javacodegeeks.snippets.enterprise.services.Employee" >
		<property name="id" value="123"/>
		<property name="position" value="marketing"/>
	</bean>

</beans>

 
Simple dependency-check applicationContext.xml
In this mode all primitive or collection types in the bean definition are checked.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-2.5.xsd">

	<bean id="personBean" class = "com.javacodegeeks.snippets.enterprise.services.Person" dependency-check="simple">
		<property name="name" value="John"/>
		<property name="employee" ref="employeeBean"/>
	</bean>
	
		<bean id="employeeBean" class="com.javacodegeeks.snippets.enterprise.services.Employee" >
		<property name="id" value="123"/>
		<property name="position" value="marketing"/>
	</bean>

</beans>

 
Object dependency-check applicationContext.xml
In this mode all objects that are reference to other beans are checked.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-2.5.xsd">

	<bean id="personBean" class = "com.javacodegeeks.snippets.enterprise.services.Person" dependency-check="objects">
		<property name="name" value="John"/>
		<property name="employee" ref="employeeBean"/>
	</bean>
	
		<bean id="employeeBean" class="com.javacodegeeks.snippets.enterprise.services.Employee" >
		<property name="id" value="123"/>
		<property name="position" value="marketing"/>
	</bean>

</beans>

 
All dependency-check applicationContext.xml
In this mode all dependencies are checked in bean definition.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-2.5.xsd">

	<bean id="personBean" class = "com.javacodegeeks.snippets.enterprise.services.Person" dependency-check="all">
		<property name="name" value="John"/>
		<property name="employee" ref="employeeBean"/>
	</bean>
	
		<bean id="employeeBean" class="com.javacodegeeks.snippets.enterprise.services.Employee" >
		<property name="id" value="123"/>
		<property name="position" value="marketing"/>
	</bean>

</beans>

 
Global dependency-check applicationContext.xml
In this mode all dependencies of all bean definitions are checked in applicationContext.xml.

<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-2.5.xsd"
	default-dependency-check="all">
	<bean id="personBean" class = "com.javacodegeeks.snippets.enterprise.services.Person">
		<property name="name" value="John"/>
		<property name="employee" ref="employeeBean"/>
	</bean>
	
		<bean id="employeeBean" class="com.javacodegeeks.snippets.enterprise.services.Employee" >
		<property name="id" value="123"/>
		<property name="position" value="marketing"/>
	</bean>

</beans>

Note that in all modes if any of the required properties is missing an UnsatisfiedDependencyException will be thrown in bean instantiation. As mentioned above, the XML-configuration checking with the dependency-check attribute is now deprecated.
 
This was an example of how to check dependencies in a Spring Bean.
 
Download the Eclipse project of this tutorial : SpringDependencyCheckingExample.zip

Theodora Fragkouli

Theodora has graduated from Computer Engineering and Informatics Department in the University of Patras. She also holds a Master degree in Economics from the National and Technical University of Athens. During her studies she has been involved with a large number of projects ranging from programming and software engineering to telecommunications, hardware design and analysis. She works as a junior Software Engineer in the telecommunications sector where she is mainly involved with projects based on Java and Big Data technologies.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

0 Comments
Inline Feedbacks
View all comments
Back to top button