June 29, 2022

Injecting List, Set or Map in Spring

When you inject dependencies in Spring using value or ref attribute you can set a single primitive value or a single referenced bean. What if you want to inject a collection of values as a bean dependency in Spring, for that Spring framework provides an option to inject collections like List, Set, Map.

Injecting collection in Spring

In Spring framework the <list/>, <set/>, <map/>, and <props/> elements set the properties and arguments of the Java Collection types List, Set, Map, and Properties, respectively.

  • <list/>: This element is used to wire a list of values in Spring. Duplicates are allowed and the order is maintained. This element can be used to wire any type of java.util.Collection and an array too.
  • <set/>: This element is similar to <list/> as it can wire a list of values and can be used to wire any type of java.util.Collection and an array too. With this element duplicates are not allowed and order is not maintained.
  • <map/>: This element is used to inject a collection of (key,value) pair in Spring with this element both key and value can be of any type.
  • <props/>: This element is used to inject a collection of (key,value) pair in Spring with a restriction that both key and value are Strings.

Injecting List and Set in Spring example

This examples shows how to inject a list or a set dependency in Spring. In the following class there is a field cityList which is of type java.util.List and field citySet which is of type java.util.Set.

public class WireCollection {
  //inject a List
  private List<String> cityList;
  //inject a Set
  private Set<String> citySet;
  public List<String> getCityList() {
    return cityList;
  }
  public void setCityList(List<String> cityList) {
    this.cityList = cityList;
  }
  public Set<String> getCitySet() {
    return citySet;
  }
  public void setCitySet(Set<String> citySet) {
    this.citySet = citySet;
  }  
}
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:context="http://www.springframework.org/schema/context"
  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.xsd">
    
  <bean id="cityBean" class="com.knpcode.springproject.service.WireCollection">
    <property name="cityList">
      <list>
        <value>Tokyo</value>
        <value>Tel Aviv</value>
        <value>Lisbon</value>
        <value>Stockholm</value>
        <value>Stockholm</value>
      </list>
    </property>
    <property name="citySet">
      <set>
        <value>Tokyo</value>
        <value>Tel Aviv</value>
        <value>Lisbon</value>
        <value>Stockholm</value>
        <value>Stockholm</value>
      </set>            
    </property>
  </bean>
</beans>

Class with main method that is used to run the example.

public class App {
  public static void main( String[] args ){
    // create context using configuration
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
    WireCollection wc =  context.getBean("cityBean", WireCollection.class);
    System.out.println("*** Cities from city list ***");
    // access the city list
    List<String> cityList =  wc.getCityList();
    for(String city : cityList) {
      System.out.println(city);
    }
    System.out.println("*** Cities from city set ***");
    // access the city set   	
    Set<String> citySet =  wc.getCitySet();
    for(String city : citySet) {
      System.out.println(city);
    }
    // close the context
    context.close();
  }
}
Output
*** Cities from city list ***
Tokyo
Tel Aviv
Lisbon
Stockholm
Stockholm
*** Cities from city set ***
Tokyo
Tel Aviv
Lisbon
Stockholm

As you can see duplicate value is rejected in the Set.

Injecting Map and Props in Spring example

public class WireCollection {
  //inject a Map
  private Map<String,Double> cities;
  //inject Properties
  private Properties cityProp;
  public Map<String, Double> getCities() {
    return cities;
  }
  public void setCities(Map<String, Double> cities) {
    this.cities = cities;
  }
  public Properties getCityProp() {
    return cityProp;
  }
  public void setCityProp(Properties cityProp) {
    this.cityProp = cityProp;
  }
}
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:context="http://www.springframework.org/schema/context"
  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.xsd">
    
  <bean id="cityBean" class="com.knpcode.springproject.service.WireCollection">
    <property name="cities">
      <map>
        <entry key="Tokyo" value="30.5" />
        <entry key="Lisbon" value="28.3" />
        <entry key="Stockholm" value="23.7" />
      </map>
    </property>
    <property name="cityProp">
      <props>
        <prop key="Tokyo">30.5</prop>
        <prop key="Lisbon">28.3</prop>
        <prop key="Stockholm">23.7</prop>
      </props>            
    </property>
  </bean>
</beans>

Class with main method that is used to run the example.

public class App {
  public static void main( String[] args ){
    // create context using configuration
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
    WireCollection wc =  context.getBean("cityBean", WireCollection.class);
    System.out.println("*** Cities from city Map ***");
    Map<String,Double> cityMap =  wc.getCities();
    for(Map.Entry<String,Double> city : cityMap.entrySet()) {
      System.out.println("In " + city.getKey() + " temperature is " + city.getValue());
    }
    System.out.println("*** Cities from city Props ***");	
    Properties cityProp =  wc.getCityProp();
    System.out.println(cityProp);
    // close the context
    context.close();
  }
}
Output
*** Cities from city Map ***
In Tokyo temperature is 30.5
In Lisbon temperature is 28.3
In Stockholm temperature is 23.7
*** Cities from city Props ***
{Tokyo=30.5, Lisbon=28.3, Stockholm=23.7}

Injecting bean reference in List, Set, Map

You can also inject a collection that holds references of another bean. In this example there is a bean called City and the list,set and Map stores object of Type City.

public class City {
  private String cityName;
  private double avgTemp;
  public String getCityName() {
    return cityName;
  }
  public void setCityName(String cityName) {
    this.cityName = cityName;
  }
  public double getAvgTemp() {
    return avgTemp;
  }
  public void setAvgTemp(double avgTemp) {
    this.avgTemp = avgTemp;
  }	
}
public class WireCollection {
  private List<City> cityList;
  private Set<City> citySet;
  private Map<String,City> cities;
  public List<City> getCityList() {
    return cityList;
  }
  public void setCityList(List<City> cityList) {
    this.cityList = cityList;
  }
  public Set<City> getCitySet() {
    return citySet;
  }
  public void setCitySet(Set<City> citySet) {
    this.citySet = citySet;
  }
  public Map<String, City> getCities() {
    return cities;
  }
  public void setCities(Map<String, City> cities) {
    this.cities = cities;
  }
}
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:context="http://www.springframework.org/schema/context"
  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.xsd">
    
  <bean id="cityBean" class="com.knpcode.springproject.model.City">
    <property name="cityName" value = "Mumbai" />
    <property name="avgTemp" value = "32.5" />
  </bean>
  <bean id="collectionBean" class="com.knpcode.springproject.service.WireCollection">
    <property name="cityList">
      <list>
        <ref bean="cityBean" />
        <bean class="com.knpcode.springproject.model.City">
          <property name="cityName" value = "Chicago" />
          <property name="avgTemp" value = "15.2" />
        </bean>
      </list>
    </property>
    <property name="citySet">
      <set>
        <ref bean="cityBean" />
        <bean class="com.knpcode.springproject.model.City">
          <property name="cityName" value = "Chicago" />
          <property name="avgTemp" value = "15.2" />
        </bean>
      </set> 
    </property>
    <property name="cities">
      <map>
        <entry key="BOM" value-ref="cityBean" />
        <entry key="CHI">
          <bean class="com.knpcode.springproject.model.City">
            <property name="cityName" value = "Chicago" />
            <property name="avgTemp" value = "15.2" />
          </bean>
        </entry>
      </map>
    </property>
  </bean>
</beans>

In the configuration you can see that in all the collections List, Set or Map bean is referenced as well as also injected as an inner bean, so there are two options for setting beans in a collection. When a bean is referenced as a key or value for a Map then key-ref or value-ref attribute is used instead of key or value.

Class with main method that is used to run the example.

public class App {
  public static void main( String[] args ){
    // create context using configuration
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("appcontext.xml");
    WireCollection wc =  context.getBean("collectionBean", WireCollection.class);
    System.out.println("*** Cities from city list ***");
    // access the city list
    List<City> cityList =  wc.getCityList();
    for(City city : cityList) {
      System.out.println("City: " + city.getCityName() + " Avg. Temp.: " + city.getAvgTemp());
    }
    	
    System.out.println("*** Cities from city set ***");
    // access the city set   	
    Set<City> citySet =  wc.getCitySet();
    for(City city : citySet) {
      System.out.println("City: " + city.getCityName() + " Avg. Temp.: " + city.getAvgTemp());
    }    	
    System.out.println("*** Cities from city Map ***");
    Map<String,City> cityMap = wc.getCities();
    for(Map.Entry<String,City> city : cityMap.entrySet()) {
      System.out.println("In " + city.getValue().getCityName() + " avg. temperature is " + city.getValue().getAvgTemp());
    }
    // close the context
    context.close();
  }
}
Output
*** Cities from city list ***
City: Mumbai Avg. Temp.: 32.5
City: Chicago Avg. Temp.: 15.2
*** Cities from city set ***
City: Mumbai Avg. Temp.: 32.5
City: Chicago Avg. Temp.: 15.2
*** Cities from city Map ***
In Mumbai avg. temperature is 32.5
In Chicago avg. temperature is 15.2

That's all for the topic Injecting List, Set or Map in Spring. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment