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:

  1. Configure the bean directly by creating a bean with class org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.
  2. By registering the <context:annotation-config/> element.
  3. 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

References

Download

You may also like...