Spring @Required Annotation Example

0

Spring @Required annotation marks a method as being required.

If the setter method is not configured with a value, then spring container will throw BeanCreationException during the initialization phase of the bean.

The required properties check happens before the container starts applying the property values on to the bean.

In this article, we will see several examples of @Required annotation including how to use a custom annotation and how to skip a required annotation check if we ever want to?

This example uses the following frameworks:

  1. Maven 3.2.3
  2. Spring 4.1.5.RELEASE
  3. Eclipse  as the IDE, version Luna 4.4.1.

Dependencies

Add the following dependencies:

  1. spring-core
  2. spring-context
  3. spring-beans

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.javarticles.spring</groupId>
	<artifactId>springListExample</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>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-beans</artifactId>
			<version>${spring.version}</version>
		</dependency>
	</dependencies>

	<properties>
		<spring.version>4.1.6.RELEASE</spring.version>
	</properties>

</project>

Required Annotation Example

Annotate the setter method with @Required annotation in order to make sure that the JavaBean property has been been configured.
In the below example, name property of Company class is annotated with @[email protected] annotation only makes sure that a property is configured with a value and doesn’t care whether the value is not null.

Company:

package com.javarticles.spring;

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

public class Company {
    private String name;

    public String getName() {
        return name;
    }

    @Required
    public void setName(String name) {
        this.name = name;
    }
    
    public String toString() {
        return "Company(" + name + ")";
    }
    
    public static Company create() {
        return new Company();
    }
}

Likewise, Employee bean’s setName() and setCompany() are annotated with @Required as we do want to know employee’s name and the company an employee belongs to.

Employee:

package com.javarticles.spring;

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

public class Employee {    
    private String name;
    private Company company;
    private int age;

    public String getName() {
        return name;
    }

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

    public Company getCompany() {
        return company;
    }

    @Required
    public void setCompany(Company company) {
        this.company = company;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public String toString() {
        return "Employee(" + name + "), " + company;
    }
}

RequiredAnnotationBeanPostProcessor is a Spring bean post processor that checks if all the bean properties with the @Required annotation have been configured. To enable this bean post processor for property checking, you must register it in the Spring IoC container. We can register the bean either using <context:annotation-config/> or <context:component-scan/> tags.

requiredPropertyMissingContext.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-2.5.xsd">

	<context:annotation-config/>
	
	<bean id="dreamCompany" class="com.javarticles.spring.Company">
		<property name="name" value="Dream Company"></property>
	</bean>
	
	<bean id="sam" class="com.javarticles.spring.Employee"/>

</beans>

When we try to load the above context XML, context fails with BeanCreationException as the required properties name and company are missing in the configuration of Employee bean.

SpringRequiredAnnotationExample:

package com.javarticles.spring;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringRequiredAnnotationExample {
    public static void main(String[] args) {
        try {
            System.out.println("Loading context file with missing required properties...");
            new ClassPathXmlApplicationContext("requiredPropertyMissingContext.xml");
        } catch (BeanCreationException e) {
            System.out.println("Bean creation failed, exception " + e.getRootCause());
        }        
    }
}

The error message contains the property names of the setter methods which are annotated with @Required but are not configured.

Output:

Loading context file with missing required properties...
Bean creation failed, exception org.springframework.beans.factory.BeanInitializationException: Properties 'company' and 'name' are required for bean 'sam'

Let’s configure the missing properties…

withRequiredPropertiesContext.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-2.5.xsd">

	<context:annotation-config/>
	
	<bean id="dreamCompany" class="com.javarticles.spring.Company">
		<property name="name" value="Dream Company"></property>
	</bean>
	
	<bean id="sam" class="com.javarticles.spring.Employee">
		<property name="name" value="Sam"/>
		<property name="company" ref="dreamCompany"/>
	</bean> 
</beans>

SpringRequiredAnnotationExample:

package com.javarticles.spring;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringRequiredAnnotationExample {
    public static void main(String[] args) {
        try {
            System.out.println("Loading context file with missing required properties...");
            new ClassPathXmlApplicationContext("requiredPropertyMissingContext.xml");
        } catch (BeanCreationException e) {
            System.out.println("Bean creation failed, exception " + e.getRootCause());
        }
        
        ClassPathXmlApplicationContext context = null;
        try {
            System.out.println("Loading context file with all required properties...");
            context = new ClassPathXmlApplicationContext("withRequiredPropertiesContext.xml");
            System.out.println(context.getBean("sam"));
        } finally {
            if (context != null) {
                context.close();
            }
        }
    }
}

Output:

Loading context file with missing required properties...
Bean creation failed, exception org.springframework.beans.factory.BeanInitializationException: Properties 'company' and 'name' are required for bean 'sam'
Loading context file with all required properties...
Employee(Sam), Company(Dream Company)

Custom Required Annotation Example

If you want to provide your own annotation type, you can do it by defining one and then manually configuring RequiredAnnotationBeanPostProcessor bean, with property requiredAnnotationType set to the custom defined annotation type.

Define a custom annotation.

CompanyRequired:

package com.javarticles.spring;

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 CompanyRequired {
}

Annotate the setter method with the above custom type.

Entrepreneur:

package com.javarticles.spring;

public class Entrepreneur {
    private String company;

    public String getCompany() {
        return company;
    }

    @CompanyRequired
    public void setCompany(String company) {
        this.company = company;
    }       
}

Register RequiredAnnotationBeanPostProcessor bean

customRequiredAnnotationContext.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-2.5.xsd">

	<bean id="" class="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
		<property name="requiredAnnotationType" value="com.javarticles.spring.CompanyRequired"/>
	</bean>
	
	<bean id="entrepreneur" class="com.javarticles.spring.Entrepreneur"/>

</beans>

SpringRequiredAnnotationExample:

package com.javarticles.spring;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringRequiredAnnotationExample {
    public static void main(String[] args) {
        try {
            System.out.println("Loading context file with missing required properties...");
            new ClassPathXmlApplicationContext("requiredPropertyMissingContext.xml");
        } catch (BeanCreationException e) {
            System.out.println("Bean creation failed, exception " + e.getRootCause());
        }
        
        ClassPathXmlApplicationContext context = null;
        try {
            System.out.println("Loading context file with all required properties...");
            context = new ClassPathXmlApplicationContext("withRequiredPropertiesContext.xml");
            System.out.println(context.getBean("sam"));
        } finally {
            if (context != null) {
                context.close();
            }
        }
        
        try {
            System.out.println("Loading context file with custom required annotation...");
            context = new ClassPathXmlApplicationContext("customRequiredAnnotationContext.xml");
        } catch (BeanCreationException e) {
            System.out.println("Bean creation failed, exception " + e.getRootCause());
        }
    }
}

Output:

Loading context file with missing required properties...
Bean creation failed, exception org.springframework.beans.factory.BeanInitializationException: Properties 'company' and 'name' are required for bean 'sam'
Loading context file with all required properties...
Employee(Sam), Company(Dream Company)
Loading context file with custom required annotation...
Bean creation failed, exception org.springframework.beans.factory.BeanInitializationException: Property 'company' is required for bean 'entrepreneur'

Required Property Check where bean is created using Static Factory Method

You can create the bean using a factory method. If any of the bean’s setter methods are annotated with @Required attribute the configuration check will still happen.

CompanyFactory:

package com.javarticles.spring;

public class CompanyFactory {
    public static Company create() {
        return new Company();
    }
}

requiredPropertyMissingFactoryMethodContext.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-2.5.xsd">

	<context:annotation-config/>
	
	<bean id="dreamCompany" class="com.javarticles.spring.CompanyFactory" factory-method="create"/>

</beans>

SpringRequiredAnnotationFactoryMethodExample:

package com.javarticles.spring;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringRequiredAnnotationFactoryMethodExample {
    public static void main(String[] args) {
        try {
            System.out.println("Loading context file with missing required properties, bean creation is through factory method ...");
            new ClassPathXmlApplicationContext("requiredPropertyMissingFactoryMethodContext.xml");
        } catch (BeanCreationException e) {
            System.out.println("Bean creation failed, exception " + e.getRootCause());
        }       
    }
}

Output:

Loading context file with missing required properties, bean creation is through factory method ...
Bean creation failed, exception org.springframework.beans.factory.BeanInitializationException: Property 'name' is required for bean 'dreamCompany'

Let’s add the missing properties.

withRequiredPropertiesFactoryMethodContext.xml:

<pre class="brush:xml">
<?xm> version="1.0" encoding="UTF-8"?>

<beans xm>ns="http://www.springframework.org/schema/beans"
	xm>ns:xsi="http://www.w3.org/2001/XM>Schema-instance"
	xm>ns:context="http://www.springframework.org/schema/context"
	xsi:schema>ocation="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-2.5.xsd">

	<context:annotation-config/>
	
	<bean id="dreamCompany" c>ass="com.javartic>es.spring.CompanyFactory" factory-method="create">
		<property name="name" va>ue="Dream Company"/>
	</bean>
</beans>

Output:

Loading context file with missing required properties, bean creation is through factory method ...
Bean creation failed, exception org.springframework.beans.factory.BeanInitializationException: Property 'name' is required for bean 'dreamCompany'
Loading context file with all required properties, bean creation is through factory method...
Company(Dream Company)

Required Property Check where bean is created using Factory Bean

You can create the bean using a factory bean. If any of the bean’s setter methods are annotated with @Required attribute the configuration check will still happen.

CompanyFactoryBean:

package com.javarticles.spring;

import org.springframework.beans.factory.FactoryBean;

public class CompanyFactoryBean implements FactoryBean {
    public static Company create() {
        return new Company();
    }

    public Company getObject() throws Exception {
        return new Company();
    }

    public Class<?> getObjectType() {
        return Company.class;
    }

    public boolean isSingleton() {
        return false;
    }
}

requiredPropertyMissingFactoryBeanContext.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-2.5.xsd">

	<context:annotation-config/>
	
	<bean id="companyFactory" class="com.javarticles.spring.CompanyFactoryBean"/>
	
	<bean id="dreamFactory" factory-bean="companyFactory"/>

</beans>

SpringRequiredAnnotationFactoryBeanExample:

package com.javarticles.spring;

import org.springframework.beans.factory.BeanCreationException;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringRequiredAnnotationFactoryBeanExample {
    public static void main(String[] args) {
        try {
            System.out.println("Loading context file with missing required properties, bean creation is through factory bean...");
            new ClassPathXmlApplicationContext("requiredPropertyMissingFactoryBeanContext.xml");
        } catch (BeanCreationException e) {
            System.out.println("Bean creation failed, exception " + e.getRootCause());
        }               
    }
}

Output:

Loading context file with missing required properties, bean creation is through factory bean...
Bean creation failed, exception java.lang.IllegalStateException: No bean class specified on bean definition

How to Skip @Required property check?

We you want the required property check to be skipped, you need to meta attribute element with key as org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.skipRequiredCheck and value set to true.

In the below example, we have configured a dummy employee bean with the ‘skipRequiredCheck’ attribute as the employee is just a dummy bean with no name or company.

skipRequiredPropertyCheckContext.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-2.5.xsd">

	<context:annotation-config />

	<bean id="dummy" class="com.javarticles.spring.Employee">
		<meta
			key="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.skipRequiredCheck"
			value="true" />
	</bean>
</beans>

SpringSkipRequiredPropertCheckExample:

package com.javarticles.spring;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringSkipRequiredPropertCheckExample {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = null;
        try {
            System.out.println("Loading context file with property marked as 'skip required property check'...");
            context = new ClassPathXmlApplicationContext("skipRequiredPropertyCheckContext.xml");
            System.out.println(context.getBean("dummy"));
        } finally {
            if (context != null) {
                context.close();
            }
        }        
    }
}

Output:

Loading context file with property marked as 'skip required property check'...
Employee(null), null

Download source code

This was an example about spring @Required annotation.

You can download the source code here: springRequiredAnnotationExample.zip
Share.

Comments are closed.