Dependency Checking with Spring @Required Annotation
This tutorial explains how to use the spring @Required
annotation. We can use this annotation to do some dependency checking at startup rather than at runtime. This makes it easier and quicker to detect exceptions or errors. By default the spring container is not configured to process this annotation, thus we need to instruct the spring container correctly. You’ll see all this in the following example.
Spring @Required Annotation Example
By annotating the setter method with @Required
you mark that property as required. Which means that when spring does the dependency checking this value must be initialized at configuration time in order for the application to boot. This property can be set by either a bean definition or through autowiring.
Here, in the StarWars
object, we have a property called TheForce
which we annotated the setter method with @Required
. We can only use the @Required
annotation on method level.
package com.memorynotfound.spring.core.required;
import org.springframework.beans.factory.annotation.Required;
public class StarWars {
private TheForce theForce;
public TheForce getTheForce() {
return theForce;
}
@Required
public void setTheForce(TheForce theForce) {
this.theForce = theForce;
}
}
Next we have our TheForce
object which is marked as required.
package com.memorynotfound.spring.core.required;
public class TheForce {
}
Configuring and Initializing
By default the @Required
annotation will not be picked up. We need to configure the RequiredAnnotationBeanPostProcessor
which is a spring bean post processor that checks if all the bean properties with the @Required
annotation have been configured correctly. To enable this bean post processor, we can either:
- Configure the bean directly by creating a bean with class
org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor
. - By registering the
<context:annotation-config/>
element. - By registering the
<context:component-scan/>
element.
<?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.xsd">
<context:annotation-config/>
<bean id="theForce" class="com.memorynotfound.spring.core.required.TheForce"/>
<bean id="luke" class="com.memorynotfound.spring.core.required.StarWars">
<property name="theForce" ref="theForce"/>
</bean>
<bean id="c3po" class="com.memorynotfound.spring.core.required.StarWars"/>
</beans>
Running the application
The container will check its required dependencies at compile time. So when we start the application, the spring container will do its dependency checking. When there are bean definitions that are missing required properties, the application will fail at startup rather than at runtime.
package com.memorynotfound.spring.core.required;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String... args) {
ApplicationContext context = new ClassPathXmlApplicationContext("app-config.xml");
StarWars starWars = (StarWars)context.getBean("luke");
System.out.println(starWars);
starWars = (StarWars)context.getBean("c3po");
System.out.println(starWars);
}
}
BeanInitializationException: Property is required
The spring container throws an exception if there are fields annotated with @Required
which are not initialized with a property. This helps detecting and avoiding common errors and exceptions at startup time rather than at runtime.
Caused by: org.springframework.beans.factory.BeanInitializationException: Property 'theForce' is required for bean 'luke'
at org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.postProcessPropertyValues(RequiredAnnotationBeanPostProcessor.java:156)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
... 11 more