Tuesday, September 15, 2015

Autowiring using Annotations





In one of my previous post I talked about XML based autowiring. Was it a hassel to configure it? If yes, then we'll look an easier way to our autowire the beans - Autowiring using Annotation.

Autowiring using Annotation can be done using several annotation methods, they are :
  • Autowired
  • Resource
  • Inject

Here we are going to discuss Autowired annotation and some other annotations. 

What's this annotation?

Annotation is a like a specifier and there are many annotations specifiers provided by Java. A basic annotation can be "@Override" specifier. 


Setting up annotation 

 

View the classes, interfaces and the XML configuration files used in this example

 

To use the annotation we'll need to add the following code to the existing configuration file. 

This code should be added to the beans tag as follows:

xmlns:context="http://www.springframework.org/schema/context"

This adds the context namespace to the XML file.

The schema location parameter too needs to be changed as follows: 

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-4.1.xsd"

The section which is highlighted is the new addition to the schema location parameter.

Finally, this last piece of code is also required to set up annotations successfully.

<context:annotation-config></context:annotation-config>

It should be added in between the beans tag.

 

Autowired Annotation

 

Here comes the long awaited section, using annotation we can reduce the XML configuration time and it's some times boring for developers to configure things up. Now let's go to the code.

package com.kasibsblog.spring.test;

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

public class AbCompany {

    private FullTimeEmployee fulltime;
    private PartTimeEmployee parttime;

    @Autowired
    public void setFulltime(FullTimeEmployee fulltime) {
        this.fulltime = fulltime;
    }

    @Autowired
    public void setParttime(PartTimeEmployee parttime) {
        this.parttime = parttime;
    }

    public void printFullTime(String name, int salary, String company) {
        fulltime.print(name, salary, company);
    }

    public void printPartTime(String name, int salary, String company) {
        parttime.print(name, salary, company);
    }

    
In the above example, the autowired annotation is placed before the setter method, this is one way of placing the autowired annotation. We can even set the annotation to only the properties, constructor or we can mix the setter methods, properties and/or the constructor. Even we can eliminate the setter methods and constructor.

Now, we'll look how we can mix single argument constructor with a property.

 
package com.kasibsblog.spring.test;
import org.springframework.beans.factory.annotation.Autowired;


public class AbCompany {
     

    @Autowired
    private FullTimeEmployee fulltime;
    private PartTimeEmployee parttime;


    @Autowired
    public AbCompany(PartTimeEmployee parttime){
        this.partttime = parttime;
    }
    public void printFullTime(String name, int salary, String company) {
        fulltime.print(name, salary, company);
    }

    public void printPartTime(String name, int salary, String company) {
        parttime.print(name, salary, company);
    }

 

 

 



Wednesday, September 9, 2015

How to deal with Ambiguities in Autowiring - Spring

In the last post - Autowiring in Spring we discussed Autowirirng and different methods of doing it. Also I gave an introduction to ambiguities in autowiring, so this tutorial is a continuation of it. 

Here I will discuss two other ways we can deal with the ambiguity in autowiring.

1. Autowiring Candidate property


 Autowiring candidate is a way to turn on or turn off autowiring of a bean and it is set per bean. Autowiring-candidate property has several choices : 
  • true - If it is set to true, then it can wire with the other bean.
  • false - If it is set to false, then it autowiring is totally prohibited.
  • default -  This is the default value set and can be considered to autowire.
Now, let's look at our sample code.

<?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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
    default-autowire="byType">

    <bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany">
    </bean>

    <bean name="parttime" class="com.kasibsblog.spring.test.PartTimeEmployee">
    </bean>
   
    <bean name="parttime2"
        class="com.kasibsblog.spring.test.PartTimeEmployee"
        autowire-candidate="false">
    </bean>

    <bean name="fulltime"
        class="com.kasibsblog.spring.test.FullTimeEmployee">

</bean>
</beans>


The bean with id - parttime2, cannot be autowired and it is prohibited. If the autowire-candidate property was set to either default or true, the program will throw an exception as the autowiring method is set to byType.



2. Primary property

 

Primary property is another technique to overcome ambiguity in autowiring. We can set the primary property to either true or false. Unlike the autowiring-candidate property set to false, primary does not totally prohibit it from autowiring only the preference level is set by it.

Let me now explain this by an example,

<?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:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
    default-autowire="byType">

    <bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany">
    </bean>

    <bean name="parttime" class="com.kasibsblog.spring.test.PartTimeEmployee">
    </bean>
   
    <bean name="parttime2"
        class="com.kasibsblog.spring.test.PartTimeEmployee"
        autowire-candidate="false">
    </bean>

    <bean name="fulltime"
        class="com.kasibsblog.spring.test.FullTimeEmployee"

        primary="true">
</bean>

<bean name="fulltime2"
        class="com.kasibsblog.spring.test.FullTimeEmployee">

</bean>
</beans>

In the above sample code, we have two beans of type - FullTimeEmploye, I had set the bean - fulltime to be my primary bean to autowire. This does not mean that fulltime2 is totally prohibited from autowiring. It can be autowired with other beans.

 

Tuesday, September 8, 2015

Autowiring in Spring

Autowiring is a technique to wire the beans together. Specially, when there are many dependencies, all of the dependencies can be  managed easily using Autowiring.

Autowiring can be performed in several methods, here are the following methods it can be done:
  1. byType
  2. byName
  3. constructor
  4. default
We can use the autowiring property of the bean to set the autowiring method.

In this example we are going to use the following classes, interface and XML file.

Employee - Interface

package com.kasibsblog.spring.test;

public interface Employee {
   
    public void print(String name, int salary, String company);

}

FullTimeEmployee - Class

package com.kasibsblog.spring.test;

public class FullTimeEmployee implements Employee {

    public void print(String name, int salary, String company) {
        System.out.println("Company : " + company + ", " + "Name : " + name + ", " + "Salary : " + salary + ",  "+ "Type : Full-Time");
    }

}

PartTimeEmployee - Class

package com.kasibsblog.spring.test;

public class PartTimeEmployee implements Employee {

    public void print(String name, int salary, String company) {
        System.out.println("Company : " + company + ", " + "Name : " + name + ", " + "Salary : " + salary + ", "
                + "Type : Part-Time");
    }
}

AbCompany - Class

package com.kasibsblog.spring.test;

public class AbCompany {

    private FullTimeEmployee fulltime;
    private PartTimeEmployee parttime;
 
    public void setFulltime(FullTimeEmployee fulltime) {
        this.fulltime = fulltime;
    }

    public void setParttime(PartTimeEmployee parttime) {
        this.parttime = parttime;
    }
   
    public void printFullTime(String name, int salary, String company){
        fulltime.print(name, salary, company);
    }
   
    public void printPartTime(String name, int salary, String company){
        parttime.print(name, salary, company);
    }

}

Main - Class

package com.kasibsblog.spring.test;

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

public class App {

    public static void main(String[] args) {

        ApplicationContext context = new ClassPathXmlApplicationContext("com/kasibsblog/spring/test/beans/beans.xml");
       
        AbCompany abcompany= (AbCompany) context.getBean("abcompany");
        abcompany.printFullTime("Sue", 12000, "Ab Company");
        abcompany.printPartTime("Mary", 10000, "Ab Company");

        ((ClassPathXmlApplicationContext) context).close();
    }

}

beans.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"
    default-init-method="init" default-destroy-method="destroy"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


    <bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany">
    </bean>

    <bean id="partTime" class="com.kasibsblog.spring.test.PartTimeEmployee">
    </bean>
   
    <bean id="fullTime" class="com.kasibsblog.spring.test.FullTimeEmployee">
    </bean>

</beans>

Now let's look at different modes of autowiring.

1. byType

Autowiring is done by using the data-type. It tries to match exactly a bean per data-type, if it finds more than a bean of the same type then an exception is thrown, also known as "Autowiring ambiguity".

  <bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany" autowiring="byType">
  </bean>

 Assume that there are two beans of FullTimeEmployee as:

<bean id="fullTime" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>

<bean id="fullTime2" class="com.kasibsblog.spring.test.FullTimeEmployee">
 </bean>

In this case, an exception would be thrown.

2. byName

Autowiring byName uses the the bean name or the bean id to wire the beans together.

<bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany" autowiring="byName">
</bean>

<bean id="fullTime" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>

<bean name="partTime" class="com.kasibsblog.spring.test.PartTimeEmployee">
</bean>

3. constructor

<bean id="abcompany" class="com.kasibsblog.spring.test.AbCompany" autowiring="constructor">
</bean>

The abcompany bean autowiring property is now set to constructor. The ABCompany class should include a two argument constructor, for this example.

public AbCompany(FullTimeEmployee fulltime, PartTimeEmployee parttime){
        this.fulltime = fulltime;
        this.parttime = parttime;
    }

The beans should match both the arguments specified in the in the constructor, otherwise it will thrown an error.

Assume that the bean with id - fulltime, has the class set to AbCompany. This will result an ambiguity as the abcompany been autowired by constructor.

<bean id="fullTime" class="com.kasibsblog.spring.test.AbCompany">
</bean>

4. default

Spring allows us to set a default autowiring which will be activated for the specified XML configuration file.

The default autowiring should be added to the beans tag in the configuration file, not the bean tag

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd"
    default-autowire="byType">

</beans>

In the above sample code, I have selected the default autowiring method as byType. We can also specify any one of the above discussed methods.

Moreover, assume that there are two beans that belongs to FullTimeEmployee class. For example,

<bean name="fulltime" class="com.kasibsblog.spring.test.FullTimeEmployee">
 </bean>

<bean name="fulltime2" class="com.kasibsblog.spring.test.FullTimeEmployee">
</bean>

In this case, an exception would be thrown since that Spring cannot detect which bean to select from the two beans. In order to eliminate this ambiguity we can specify what bean should be used to wire with the "abcompany" bean.

We can achieve this by using the default-autowing-candidates property of the beans tag.

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"
    default-autowire="byType" default-autowire-candidates="fulltime,parttime">

</beans>

Here the fulltime and partime beans areselected as the default-autowire-candidates. It is a comma seperated list also note that the list cannot contain any white spaces.

Using wildcards to specify default-autowire-candidates

Wildcards can be used to specify the default candidates, an asterisk(*) is used as the wildcard character.

In our example, both the beans end with "time" - fulltime & parttime. The code can be changed to 

default-autowire-candidates="*time"