Thursday, March 24, 2022

Wiring Collections in Spring

In the post dependency injection in spring you would have seen examples of configuring both property values and reference to other beans. But these attributes property and ref can only be used with single fields. If you want to wire collections then Spring provides four options List, Set, Map and Props.


Options to wire collections in Spring

  • <list>- Used to wire a list of values in Spring, works with properties of any type of java.util.Collection and also arrays. As in Java list attribute allows duplicates, order is maintained.
  • <set>- Same as list with couple of differences - doesn’t allow duplicates, insertion order not maintained.
  • <map>- Used to wire a collection of (key, value) pair in Spring. Both key and value can be of any type.
  • <props>- Used to wire a collection of (key, value) pair. Both key and value have to be Strings.

Wiring List and Set in Spring example

Order class

Java class which has both List and Set fields.

import java.util.List;
import java.util.Set;

public class Order {
    private String id;
    private List<String> itemList;
    private Set<String> itemSet;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public List<String> getItemList() {
        return itemList;
    }
    public void setItemList(List<String> itemList) {
        this.itemList = itemList;
    }
    public Set<String> getItemSet() {
        return itemSet;
    }
    public void setItemSet(Set<String> itemSet) {
        this.itemSet = itemSet;
    }   
}

XML Configuration

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
  <bean id="orderBean" class="org.netjs.prog.Order">
    <property name="id" value = "1" />
    <property name="itemList">
      <list>
        <value>Laptop</value>
        <value>RAM</value>
        <value>Drive</value>
        <value>Drive</value>
      </list>
    </property>
    <property name="itemSet">
      <set>
        <value>Laptop</value>
        <value>RAM</value>
        <value>Drive</value>
        <value>Drive</value>
      </set>            
    </property>
  </bean>
</beans>

You can run it using the following Java program-

import java.util.List;
import java.util.Set;
import org.netjs.prog.Order;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
        ("appcontext.xml");
   
    Order orderBean = (Order) context.getBean("orderBean");
    List<String> itemList = orderBean.getItemList();
    for(String item : itemList){
      System.out.println("item from List - " + item);
    }
    
    Set<String> itemSet = orderBean.getItemSet();
    for(String item : itemSet){
      System.out.println("item from set - " + item);
    }
  }
}

Output

creating instance of class Admin
creating instance of class Admin
item from List - Laptop
item from List - RAM
item from List - Drive
item from List - Drive
item from set - Laptop
item from set - RAM
item from set - Drive

Here it can be noted that Set has not stored duplicate value.

As mentioned above, List and Set can wire any type of java.util.Collection and also arrays, you can check it by changing the List and Set in Order class respectively to-

private String[] itemList;
private Collection<String> itemSet

without changing anything in XML configuration and it will work just fine.

Bean reference with List and Set

You can reference another bean too while wiring a List or Set.
Let's say we have two classes Order and Item.

Order class

import java.util.List;
import java.util.Set;

public class Order {
    private String id;
    private List<Item> itemList;
    private Set<Item> itemSet;
    public String getId() {
        return id;
    }
    public void setId(String id) {
        this.id = id;
    }
    public List<Item> getItemList() {
        return itemList;
    }
    public void setItemList(List<Item> itemList) {
        this.itemList = itemList;
    }
    public Set<Item> getItemSet() {
        return itemSet;
    }
    public void setItemSet(Set<Item> itemSet) {
        this.itemSet = itemSet;
    }    
}

Item Class

public class Item {
    private String name;
    private double price;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public double getPrice() {
        return price;
    }
    public void setPrice(double price) {
        this.price = price;
    }  
}

XML Configuration

<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">

  <bean id="itemBean" class="org.netjs.prog.Item" >
    <property name="name" value = "Laptop" />
    <property name="price" value = "300.45" />
  </bean>
  <bean id="orderBean" class="org.netjs.prog.Order">
    <property name="id" value = "1" />
    <property name="itemList">
      <list>
        <ref bean="itemBean" />
        <bean class="org.netjs.prog.Item">
          <property name="name" value = "RAM" />
          <property name="price" value = "34.78" />
        </bean>
      </list>
    </property>
    <property name="itemSet">
      <set>
        <ref bean="itemBean" />
        <bean class="org.netjs.prog.Item">
          <property name="name" value = "Drive" />
          <property name="price" value = "50.67" />
        </bean>
      </set>        
    </property>
  </bean>
</beans>

Note here in Configuration there are two ways to refer another bean, you can either give a reference using ref attribute or within a list attribute you can define a bean.

You can run this using the following Java program.

import org.netjs.prog.Item;
import org.netjs.prog.Order;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
      ("appcontext.xml");
   
    Order orderBean = (Order) context.getBean("orderBean");
    List<Item> itemList = orderBean.getItemList();
    for(Item item : itemList){
      System.out.println("item from List - " + item.getName() + 
        " " + item.getPrice());
    }
    
    Set<Item> itemSet = orderBean.getItemSet();
    for(Item item : itemSet){
      System.out.println("item from set - " + item.getName() + " " + item.getPrice());
    }
  }
}

Output

creating instance of class Admin
creating instance of class Admin
item from List - Laptop 300.45
item from List - RAM 34.78
item from set - Laptop 300.45
item from set - Drive 50.67

Wiring Map and properties in Spring framework

With Map, Key and Value can be String or any other type so there are four options altogether, two for key and two for value.

  • key - Specifies the key of the map entry as a String
  • key-ref - Specifies the key of the map entry as a reference to another bean.
  • value - Specifies the value of the map entry as a String
  • value-ref - Specifies the value of the map entry as a reference to another bean.

With properties both key and value have to be String.

Order class

 
import java.util.Map;
import java.util.Properties;

public class Order {
  private String id;
  private Map<String, Item> itemMap;
  private Properties itemProp;
  public String getId() {
    return id;
  }
  public void setId(String id) {
    this.id = id;
  }
  public Map<String, Item> getItemMap() {
    return itemMap;
  }
  public void setItemMap(Map<String, Item> itemMap) {
    this.itemMap = itemMap;
  }
  public Properties getItemProp() {
    return itemProp;
  }
  public void setItemProp(Properties itemProp) {
    this.itemProp = itemProp;
  }    
}

Item Class

 
public class Item {
 private String name;
 private double price;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public double getPrice() {
  return price;
 }
 public void setPrice(double price) {
  this.price = price;
 } 
}

XML Configuration

 
<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans 
    http://www.springframework.org/schema/beans/spring-beans-4.0.xsd">
    
  <bean id="itemBean" class="org.netjs.prog.Item" >
    <property name="name" value = "Laptop" />
    <property name="price" value = "300.45" />
  </bean>
  <bean id="orderBean" class="org.netjs.prog.Order">
    <property name="id" value = "1" />
    <property name="itemMap">
      <map>
        <entry key="1" value-ref="itemBean" />
        <entry key="2">
          <bean class="org.netjs.prog.Item">
            <property name="name" value = "RAM" />
            <property name="price" value = "34.78" />
          </bean>
        </entry>
      </map>
    </property>
    <property name="itemProp">
      <props>
        <prop key="Laptop">500</prop>
        <prop key="RAM">56.89</prop>
      </props>      
    </property>
  </bean>
</beans>

Here note that with Map also reference can be provided using the ref attribute or as inner bean definition.

You can run it using the following Java program.

 
import java.util.Map;
import java.util.Properties;
import org.netjs.prog.Item;
import org.netjs.prog.Order;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App {
  public static void main(String[] args) {
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext
       ("appcontext.xml");
   
    Order orderBean = (Order) context.getBean("orderBean");
    Map<String, Item> itemMap = orderBean.getItemMap();
    for(Map.Entry<String, Item> item : itemMap.entrySet()){        
      System.out.println("item from Map - " + item.getKey() + " " + 
      item.getValue().getName() + " " +  item.getValue().getPrice());
    }
    Properties itemProp = orderBean.getItemProp();
    System.out.println("items from Properties " + itemProp);
  }
} 

Output

creating instance of class Admin
creating instance of class Admin
item from Map - 1 Laptop 300.45
item from Map - 2 RAM 34.78
items from Properties {Laptop=500, RAM=56.89}

That's all for this topic Wiring Collections in Spring. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Dependency Injection Using factory-method in Spring
  2. Autowiring Using XML Configuration in Spring
  3. Autowiring Using Annotations in Spring
  4. Data Access in Spring Framework
  5. Using depends-on Attribute in Spring

You may also like-

  1. Spring Component Scan to Automatically Discover Beans
  2. Lazy Initialization in Spring Using lazy-init And @Lazy Annotation
  3. Bean Definition Inheritance in Spring
  4. Spring MessageSource Internationalization (i18n) Support
  5. Executor And ExecutorService in Java With Examples
  6. Synchronization in Java - Synchronized Method And Block
  7. Producer-Consumer Java Program Using wait notify
  8. Java Program to Find The Longest Palindrome in a Given String