Showing posts with label Required. Show all posts
Showing posts with label Required. Show all posts

Sunday, September 2, 2012

@Required Annotation in spring

The @Required annotation applies to bean property setter methods, as in the following example:

package org.arpit.javapostsforlearning;

public class Country {

  Capital capital; 

  @Required
  public void setCapital(Capital capital) {
        this.capital = capital;
    }
}

This annotation simply indicates that the affected bean property must be populated at configuration time: either through an explicit property value in a bean definition or through autowiring. The container will throw an exception if the affected bean property has not been populated; this allows for eager and explicit failure, avoiding NullPointerExceptions or the like later on.

Suppose you have very large application and you get   NullPointerExceptions because required dependency has not been injected then it is very hard to find out what goes wrong.So this annotation helps us in debugging the code.

Example:

For configuring spring in your eclipse ide please refer  hello world example

1.Country.java:

This is simple pojo class having some attributes so here country has name and object of Capital class.
Create Country.java under package org.arpit.javapostsforlearning.Copy following content into Country.java.

package org.arpit.javapostsforlearning;
import org.springframework.beans.factory.annotation.Required;
public class Country {

    String countryName;
    Capital capital;
    public String getCountryName() {
        return countryName;
    }
    public void setCountryName(String countryName) {
        this.countryName = countryName;
    }
    public Capital getCapital() {
        return capital;
    }

  @Required
    public void setCapital(Capital capital) {
        this.capital = capital;
    }
}

2.Capital.java

This is also simple pojo class having one attribute called "capitalName".
Create Capital.java under package org.arpit.javapostsforlearning.java.Above Country class contains object of this class.Copy following content into Capital.java

package org.arpit.javapostsforlearning;

public class Capital {

    String capitalName;

    public String getCapitalName() {
        return capitalName;
    }

    public void setCapitalName(String capitalName) {
        this.capitalName = capitalName;
    }
}

3.RequiredAnnotationInSpringMain.java

This class contains main function.Create RequiredAnnotationInSpringMain.java under package org.arpit.javapostsforlearning.Copy following content into RequiredAnnotationInSpringMain.java

 package org.arpit.javapostsforlearning;

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

public class RequiredAnnotationInSpringMain{

    public static void main(String[] args) {
        ApplicationContext appContext = new ClassPathXmlApplicationContext("ApplicationContext.xml");

        Country countryObj = (Country) appContext.getBean("CountryBean");
        String countryName=countryObj.getCountryName();
Capital capital=countryObj.getCapital();
        String capitalName=capital.getCapitalName();
        System.out.println(capitalName+" is capital of "+countryName);
      
    }
}

4.ApplicationContext.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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<bean id="CountryBean" class="org.arpit.javapostsforlearning.Country">
<property name="countryName" value="India" />
</bean>
<bean id="CaptialBean" class="org.arpit.javapostsforlearning.Capital">
<property name="capitalName" value="Delhi" />
</bean>
</beans>

Now you can note here that we have not injected capital property into country class but we have used it for getting capitalName in RequiredAnnotationInSpringMain class.

5.Run it:

When you will run above application,you will get following as output.

Sep 01, 2012 1:43:16 PM org.springframework.context.support.AbstractApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@17a1767: startup date [Sat Sep 01 13:43:16 IST 2012]; root of context hierarchy
Sep 01, 2012 1:43:17 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [ApplicationContext.xml]
Sep 01, 2012 1:43:17 PM org.springframework.beans.factory.support.DefaultListableBeanFactory preInstantiateSingletons
INFO: Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@54446d: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,CountryBean,CaptialBean,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy
Sep 01, 2012 1:43:17 PM org.springframework.beans.factory.support.DefaultSingletonBeanRegistry destroySingletons
INFO: Destroying singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@54446d: defining beans [org.springframework.context.annotation.internalConfigurationAnnotationProcessor,org.springframework.context.annotation.internalAutowiredAnnotationProcessor,org.springframework.context.annotation.internalRequiredAnnotationProcessor,org.springframework.context.annotation.internalCommonAnnotationProcessor,CountryBean,CaptialBean,org.springframework.context.annotation.ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor#0]; root of factory hierarchy
Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'CountryBean' defined in class path resource [ApplicationContext.xml]: Initialization of bean failed; nested exception is org.springframework.beans.factory.BeanInitializationException: Property 'capital' is required for bean 'CountryBean'
    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:294)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:225)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:291)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:585)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:913)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:464)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at org.arpit.javapostsforlearning.SetterInjectionMain.main(SetterInjectionMain.java:11)
Caused by: org.springframework.beans.factory.BeanInitializationException: Property 'capital' is required for bean 'CountryBean'
    at org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor.postProcessPropertyValues(RequiredAnnotationBeanPostProcessor.java:149)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1106)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517)
    ... 11 more

When you run it,you will get exception complaining "Property 'capital' is required for bean 'CountryBean'"

Saturday, September 1, 2012

Annotation based Configuration in spring

This is 13 of 13 parts of tutorial series

Tutorial Content:



Part-1:Introduction to spring framework
Part-2:Dependency injection(ioc) in spring
Part-3:Spring hello world example in eclipse
Part-4:Dependency injection via setter method in spring
Part-5:Dependency injection via constructor in spring
Part-6:Spring Bean scopes with examples
Part-7:Initializing collections in spring
Part-8:Beans Autowiring in spring
Part-9:Inheritance in Spring
Part-10:Spring ApplicationContext
Part-11:Spring lifetime callbacks
Part-12:BeanPostProcessors in Spring
Part-13:Annotation based Configuration in spring

There are two ways via which you can inject dependency in spring
  1. By configuring XML.
  2. By using annotation.
In all our previous posts,we have injected dependency by configuring XML file but instead of doing this,we can move the bean configuration into the component class itself by using annotations on the relevant class, method, or field declaration.

You might think what if you have done both i.e.used annotations and XML both.In that case,XML configuration will override annotations because XML configuration will be injected after annotations.

Now annotations based configuration is turned off by default so you have to turn it on by entering <context:annotation-config/> into spring XML file.

ApplicationContext.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-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<context:annotation-config/>
<!-- beans declaration goes here -->
</beans>

Now you are ready to use annotations in your code.Let us discuss few important annotations in spring

@Required:

 The @Required annotation applies to bean property setter methods.

@Autowired:

The @Autowired annotation can apply to bean property setter methods, non-setter methods, constructor and properties.

 @Qualifier:

The @Qualifier annotation along with @Autowired can be used to remove the confusion by specifiying which exact bean will be wired.

 JSR 250 Annotations: 

Spring supports JSR-250 based annotations which include @Resource, @PostConstruct and @PreDestroy annotations.