Rajinder Menu

Collaborators




Earlier we have read in constructor injection and setter injection that how we can set a reference to a bean( target bean) as the value of a property of some other bean using ref attribute of <property> and <constructor-arg> tags.

Collaborator means reference to a bean i.e reference of target bean.

Instead of ref attribute we can also use ref element inside <property> and <constructor-arg> tags in order to set the value of a property to a reference of some bean. This is shown below:

Car.java
package di.collaborators;

public class Car {
    private int year;
    private String make;
    private Wheel wheel;

    /*Constructor*/
    Car(int year, String make,Wheel wheel){
     this.year = year;
     this.make = make;
     this.wheel = wheel;
 
    }
 
    void carDetails(){
        System.out.println("Make: "+make);
        System.out.println("Year: "+year);
        System.out.println("Wheel Details:");
        wheel.wheelDetails();
    }
}

Wheel.java
package di.collaborators;

public class Wheel{

    private String company;

    Wheel(String company){
    this.company = company;
    }
   
    void wheelDetails(){
        System.out.println("    Company: "+company);
    }
}

test.java
package di.collaborators;

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

public class test{

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

ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
">

<bean id="myCar" class="di.collaborators.Car">
<constructor-arg value="2013"/>
<constructor-arg value="Honda"/>
<constructor-arg>
<!--Collaborator i.e reference to a 'Wheel' object-->
<ref  local="myCarWheels"/>
</constructor-arg>
</bean>

<bean id="myCarWheels" class="di.collaborators.Wheel">
<constructor-arg value="Ceat"/>
</bean>
</beans>

Output
Make: Honda
Year: 2013
Wheel Details:
    Company: Ceat

The ref element has three attributes namely - local, bean and parent.

'local' attribute:

When 'local' attribute of ref tag is used as :

<bean id="myCar" class="di.collaborators.Car">
<constructor-arg value="2013"/>
<constructor-arg value="Honda"/>
<constructor-arg>
<ref local="myCarWheels"/>
</constructor-arg>
</bean>

<bean id="myCarWheels" class="di.collaborators.Wheel">
<constructor-arg value="Ceat"/>
</bean>

then both the dependent bean and its dependency must be in same xml file.

Here myCar is dependent bean and myCarWheels ( target bean) is its dependency. Thus if we are using local attribute of ref tag then both myCar and myCarWheels must be declared  in same xml file. Suppose they are defined in different xml files as:

ApplicationContext.xml
<beans...>
<bean id="myCar" class="di.collaborators.Car">
<constructor-arg value="2013"/>
<constructor-arg value="Honda"/>
<constructor-arg>
<ref local="myCarWheels"/>
</constructor-arg>
</bean>
</beans>

secondAppplicationContext.xml
<beans...>
<bean id="myCarWheels" class="di.collaborators.Wheel">
<constructor-arg value="Ceat"/>
</bean>
</beans>

then you will get following error upon running the program:

Caused by: org.xml.sax.SAXParseException: cvc-id.1: There is no ID/IDREF binding for IDREF 'myCarWheels'.

'bean' attribute:

In this case where dependent bean and its dependency are not in same xml file, you should use 'bean' attribute as shown below:

ApplicationContext.xml
<beans...>
<bean id="myCar" class="di.collaborators.Car">
<constructor-arg value="2013"/>
<constructor-arg value="Honda"/>
<constructor-arg>
<ref  bean="myCarWheels"/>
</constructor-arg>
</bean>
</beans>

secondAppplicationContext.xml
<beans...>
<bean id="myCarWheels" class="di.collaborators.Wheel">
<constructor-arg value="Ceat"/>
</bean>
</beans>

test.java(changed)
package di.collaborators;

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

public class test{

public static void main(String args[]){
   
    ApplicationContext appContext = new ClassPathXmlApplicationContext("ApplicationContext.xml","secondApplicationContext.xml");
   
    Car myCar = (Car) appContext.getBean("myCar");
    myCar.carDetails();
   
    }
}

Car.java and Wheel.java remains same as above.

Output
Make: Honda
Year: 2013
Wheel Details:
    Company: Ceat

Similarly, ref tag can also be used in <property> tags as shown below:

<bean id="myCar" class="di.collaborators.Car">
<property name="year" value="2013"/>
<property name="make" value="Honda"/>
<property name="wheel">
<ref local="myCarWheels"/>
</property>
</bean>

<bean id="myCarWheels" class="di.collaborators.Wheel">
<property name="company" value="Ceat"/>
</bean>

For using <property> tags you have to put setters and getters in Car.java and Wheel.java.


I would like to know your comments and if you liked the article then please share it on social networking buttons.


1 comment: