Flying_Machine Flying_Machine - 1 month ago 8
Java Question

Error in creation of bean while using @Required and @Autowired

I am new to spring.I am trying to make use

@Required
and
@Autowired
in my code but its giving me
org.springframework.beans.factory.BeanCreationException
.Below is my code.

1) StudentAuto.java

public class StudentAuto
{

@Autowired
private String name;
@Autowired
private String city;
public String getCity() {
return city;
}
@Required
public void setCity(String city) {
this.city = city;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}


2)spring.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config></context:annotation-config>
<bean id='stu' class='com.bean.StudentAuto' >
</bean>

<bean name='name' class='java.lang.String'>
<constructor-arg value="nm"></constructor-arg>
</bean>

<bean name='city' class='java.lang.String'>
<constructor-arg value="ci"></constructor-arg>
</bean>
</beans>


3)TestApp.java

public class TestApp {

/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
ApplicationContext context=new ClassPathXmlApplicationContext("spring.xml");
StudentAuto auto=context.getBean("stu", StudentAuto.class);
System.out.println(auto.getCity());
System.out.println(auto.getName());
}
}


and error stack trace is below.

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'stu' defined in class path resource [spring.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Property 'city' is required for bean 'stu'
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:527)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456)
at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:194)
at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1079)
at com.bean.TestApp.main(TestApp.java:14)
Caused by: org.springframework.beans.factory.BeanInitializationException: Property 'city' is required for bean 'stu'
at org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.postProcessPropertyValues(RequiredAnnotationBeanPostProcessor.java:149)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1074)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
... 7 more


Please help me on this issue.

Answer

The javadoc for @Required states

Marks a method (typically a JavaBean setter method) as being 'required': that is, the setter method must be configured to be dependency-injected with a value.

Note that the annotated method is not necessarily a setter but that is usually what it is.

@Required methods are processed by RequiredAnnotationBeanPostProcessor which states that

This neatly pushes responsibility for such checking onto the container (where it arguably belongs), and obviates the need (in part) for a developer to code a method that simply checks that all required properties have actually been set.

So the purpose is to guarantee that properties are set by checking if the container has actually invoked the method.

The typical pattern is

class Foo {
    private String value;
    @Required
    public void setValue(String value) {
        this.value = value;
    }
}

with a bean definition

<bean class="Foo" id="fooBean">
    <property name="value" value="some value"/>
</bean>

If you had not added the <property>, the container would complain and throw exceptions, just like it does with your configuration

<bean id='stu' class='com.bean.StudentAuto' >
</bean>

Here, the container is not using the @Required method to set the property. It is using reflection on the Field directly because of @Autowired. Therefore the @Required annotation is not validated.

Comments