3.5 Collections

Basic bean creation has now been covered, but Spring also has specific bean support for Collections. There are list, set, map, and props elements. References to beans, value elements, and inner beans can be used to set values inside lists. So all the basic bean concepts learned earlier can be applied inside Collection specific elements.

List

The list element will create a list that can be injected into a constructor or property that takes a java.util.List.

Example 3.17. List Element

The first bean definition shows a List of Strings being set. The second bean definition shows a List of Messages using references and an inner bean definition to create the list.

Excerpt from chapter03-collections/src/main/resources/list-applicationContext.xml
                    
<bean id="stringMessageList"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="messageList">
        <list>
            <ref local="stringMessage01"/>
            <ref local="stringMessage02"/>
            <value>Spring is fun to learn.</value>
        </list>
    </property>
</bean>

<bean id="messageList"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="messageList">
        <list>
            <ref local="message01"/>
            <ref local="message02"/>
            <bean class="org.springbyexample.springindepth.bean.Message">
                <property name="message" value="Spring is fun to learn." />
            </bean>
        </list>
    </property>
</bean>
                    
                

Example 3.18. List Factory

This example uses a FactoryBean to create a List directly as the bean instead of setting it as a property on another bean. This way a bean can be created and inserted into multiple bean definitions.

Excerpt from chapter03-collections/src/main/resources/list-applicationContext.xml
                    
<!-- String message factory list. -->
<bean id="messageFactoryList" 
      class="org.springframework.beans.factory.config.ListFactoryBean">
    <property name="sourceList">
        <list>
            <ref bean="stringMessage01"/>
            <ref bean="stringMessage02"/>
            <value>Spring is fun to learn.</value>
        </list>
    </property>
</bean>
                    
                

Example 3.19. List Util

Another custom namespace utility is for creating lists. The first bean definition is identical to the ListFactoryBean example except it's a little shorter and easier to read. The second bean definition is the same except it uses the list-class attribute to specify what List implementation to use. When the list-class attribute isn't used, the ApplicationContext will choose the implementation class.

Excerpt from chapter03-collections/src/main/resources/list-applicationContext.xml
                    
<util:list id="messageUtilList">
    <ref bean="stringMessage01"/>
    <ref bean="stringMessage02"/>
    <value>Spring is fun to learn.</value>
</util:list>

<util:list id="messageUtilLinkedList" 
           list-class="java.util.LinkedList">
    <ref bean="stringMessage01"/>
    <ref bean="stringMessage02"/>
    <value>Spring is fun to learn.</value>
</util:list>
                    
                

Set

The set element will create a java.util.Set that can be injected into a constructor or property. Using a Set is identical to using a List except a Set will only have unique values. Since it is a Set, multiple references to the same bean or beans that are equal will only keep one reference inside the Set.

Example 3.20. Set Element

Excerpt from chapter03-collections/src/main/resources/set-applicationContext.xml
                    
<bean id="stringMessageSet"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="messageSet">
        <set>
            <ref local="stringMessage01"/>
            <ref local="stringMessage02"/>
            <value>Spring is fun to learn.</value>
        </set>
    </property>
</bean>

<bean id="messageSet"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="messageSet">
        <set>
            <ref local="message01"/>
            <ref local="message02"/>
            <bean class="org.springbyexample.springindepth.bean.Message">
                <property name="message" value="Spring is fun to learn." />
            </bean>
        </set>
    </property>
</bean>
                    
                

Example 3.21. Set Factory

This example uses a FactoryBean to create a Set directly as a bean definition.

Excerpt from chapter03-collections/src/main/resources/set-applicationContext.xml
                    
<bean id="messageFactorySet" 
      class="org.springframework.beans.factory.config.SetFactoryBean">
    <property name="sourceSet">
        <set>
            <ref bean="stringMessage01"/>
            <ref bean="stringMessage02"/>
            <value>Spring is fun to learn.</value>
        </set>
    </property>
</bean>
                    
                

Example 3.22. Set Util

The following example uses the util namespace to create a Set. The first bean definition is the same as the SetFactoryBean example and the second definition uses the set-class attribute to have the Set implementation be a java.util.TreeSet. Once again, if the set-class attribute isn't specified, the ApplicationContext will choose the implementation.

Excerpt from chapter03-collections/src/main/resources/set-applicationContext.xml
                    
<util:set id="messageUtilSet">
    <ref bean="stringMessage01"/>
    <ref bean="stringMessage02"/>
    <value>Spring is fun to learn.</value>
</util:set>

<util:set id="messageUtilTreeSet" 
          set-class="java.util.TreeSet">
    <ref bean="stringMessage01"/>
    <ref bean="stringMessage02"/>
    <value>Spring is fun to learn.</value>
</util:set>
                    
                

Map

The map element will create a java.util.Map that can be injected into a constructor or property. The map element expects an entry element inside it to define key/value pairs for the Map. There are a few different ways to create the entry element. One way is to have a value element, ref element, or bean element nested inside the key element for the key or inside the entry element for the value.

Creating beans this way is very verbose, but there are shortcut attributes on the entry element. The key attribute uses the attribute as a value and the key-ref uses the attribute value as a reference. Just like the ref attribute on the constructor-arg and property elements inside a bean definition, the key-ref attribute is equivalent to a ref element's bean attribute. There isn't a shortcut for the ref element's local attribute. There are also value and value-ref attributes with the same behavior as the key and key-ref attributes, but these obviously set the value for each entry.

Example 3.23. Map Element

The first bean definition injects a Map using String messages and the second bean definition injects a Map of Message instances.

Excerpt from chapter03-collections/src/main/resources/map-applicationContext.xml
                    
<bean id="stringMessageMap"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="messageMap">
        <map>
            <entry>
                <key>
                    <value>1</value>
                </key>
                <ref local="stringMessage01"/>
            </entry>
            <entry key="2" value-ref="stringMessage02" />
            <entry key-ref="key03" value="Spring is fun to learn." />
        </map>
    </property>
</bean>

<bean id="messageMap"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="messageMap">
        <map>
            <entry key="1" value-ref="message01" />
            <entry key="2" value-ref="message02" />
            <entry key-ref="key03">
                <bean class="org.springbyexample.springindepth.bean.Message">
                    <property name="message" value="Spring is fun to learn." />
                </bean>
            </entry>
        </map>
    </property>
</bean>
                    
                

Example 3.24. Map Factory

Example creating a Map as a bean definition using the MapFactoryBean.

Excerpt from chapter03-collections/src/main/resources/map-applicationContext.xml
                    
<bean id="messageFactoryMap"
      class="org.springframework.beans.factory.config.MapFactoryBean">
    <property name="sourceMap">
        <map>
            <entry>
                <key>
                    <value>1</value>
                </key>
                <ref bean="stringMessage01"/>
            </entry>
            <entry key="2" value-ref="stringMessage02" />
            <entry key-ref="key03" value="Spring is fun to learn." />
        </map>
    </property>
</bean>
                    
                

Example 3.25. Map Util

Another example using the util namespace with the second bean definition setting the map-class attribute so it will us the java.util.TreeMap implementation.

Excerpt from chapter03-collections/src/main/resources/map-applicationContext.xml
                    
<util:map id="messageUtilMap">
    <entry>
        <key>
            <value>1</value>
        </key>
        <ref bean="stringMessage01"/>
    </entry>
    <entry key="2" value-ref="stringMessage02" />
    <entry key-ref="key03" value="Spring is fun to learn." />
</util:map>

<util:map id="messageUtilTreeMap" 
          map-class="java.util.TreeMap">
    <entry>
        <key>
            <value>1</value>
        </key>
        <ref bean="stringMessage01"/>
    </entry>
    <entry key="2" value-ref="stringMessage02" />
    <entry key-ref="key03" value="Spring is fun to learn." />    
</util:map>
                    
                

Properties

The props element will create a java.util.Properties that can be injected into a constructor or property. A property key/value pair can be added to the props element using the prop element. The prop element is less flexible than the previous Collection elements that have been covered so far because Properties only support a String for the key and value. The prop element has a key attribute to set the key and inside the prop element the value can be specified.

Example 3.26. Props Element

The first bean definition shows creating a Properties instance using the props element. The second bean definition shows a shortcut where Spring parses a String as if it was an external properties file. Typically Spring always has well formed XML with discreet values either in attributes or elements. The shortcut could be nice if you have an external file that you want to move into your Spring configuration or you may want to start with this in your Spring configuration and later move it to a separate file if it grows larger.

Excerpt from chapter03-collections/src/main/resources/properties-applicationContext.xml
                    
<bean id="messageProperties"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="messageProperties">
        <props>
            <prop key="1">Spring is easy.</prop>
            <prop key="2">Spring is useful.</prop>
            <prop key="3">Spring is fun to learn.</prop>
        </props>
    </property>
</bean>

<bean id="messagePropertiesShortcut"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="messageProperties">
        <value>
            1=Spring is easy.
            2=Spring is useful.
            3=Spring is fun to learn.
        </value>
    </property>
</bean>
                    
                

Example 3.27. Properties Factory

The PropertiesFactoryBean is used to create a bean that represents a java.util.Properties instance.

Excerpt from chapter03-collections/src/main/resources/properties-applicationContext.xml
                    
<bean id="messageFactoryProperties" 
      class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="properties">
        <props>
            <prop key="1">Spring is easy.</prop>
            <prop key="2">Spring is useful.</prop>
            <prop key="3">Spring is fun to learn.</prop>
        </props>
    </property>
</bean>
                    
                

Example 3.28. Properties Util

This first bean definition uses util:properites to create an instance using information set on it and the second uses util:properties to read from a properties file. The location attribute's value will be resolved by the resource type of the default resource loader the ApplicationContext uses. In the unit tests the default resource loader uses the classpath resource loader. If this wasn't the default, setting the location to “classpath:/message.properties” would force the resource loader to use the classpath. The different types of resource loaders available in Spring will be covered in more detail later.

Excerpt from chapter03-collections/src/main/resources/properties-applicationContext.xml
                    
<util:properties id="messageUtilProperties">
    <prop key="1">Spring is easy.</prop>
    <prop key="2">Spring is useful.</prop>
    <prop key="3">Spring is fun to learn.</prop>
</util:properties>

<util:properties id="messageUtilFileProperties" 
                 location="/message.properties"/>
                    
                

Java 5 Generics Typed Collections

Spring has Java 5 generics support for typed Collections. If the type expected by a Collection doesn't match, Spring will try to convert any values to this type. For example if there is a List<Integer> and a list element with a value of '3' is being injected into it, Spring will convert the '3' into an Integer so the list can be safely injected.

Example 3.29. Java5 Generics Typed Collection

The following example has a typed Map, but this applies to Lists and Sets also. This example takes the previous bean definition Map example where the value is a Message instance and sets it on the typedMessageMap property. The Map is set to have an Integer for the key and a Message for the value.

Excerpt from chapter03-collections/src/main/java/org/springbyexample/springindepth/chapter03/collections/MessageContainer.java
                    
/**
 * Gets <code>Map&lt;Integer, Message&gt;</code> of messages.
 */
public Map<Integer, Message> getTypedMessageMap() {
    return typedMessageMap;
}

/**
 * Sets <code>Map&lt;Integer, Message&gt;</code> of messages.
 */
public void setTypedMessageMap(Map<Integer, Message> typedMessageMap) {
    this.typedMessageMap = typedMessageMap;
}
                    
                

When the values are injected, Spring will try to perform any type conversion it would for setting a standard property for a typed collection. In this case the key is a String in the XML configuration, but is converted to an Integer as it is set. No type conversion needs to be performed because the value is already a Message.

Excerpt from chapter03-collections/src/main/resources/map-applicationContext.xml
                    
<bean id="typedMessageMap"
      class="org.springbyexample.springindepth.chapter03.collections.MessageContainer">
    <property name="typedMessageMap">
        <map>
            <entry key="1" value-ref="message01" />
            <entry key="2" value-ref="message02" />
            <entry key-ref="key03">
                <bean class="org.springbyexample.springindepth.bean.Message">
                    <property name="message" value="Spring is fun to learn." />
                </bean>
            </entry>
        </map>
    </property>
</bean>
                    
                

Enums

Spring has support has support for Java 5 enums and pre Java 5 type-safe emulated enums. Spring will automatically detect the enumeration class on the setter and use the text value from the property setting the enumeration to look up the appropriate enum to set on the class.

Example 3.30. Java 5 Enums

The following example shows a Fruit enum that has the values APPLE, ORANGE, and PEAR. The FruitBasket class can have a Fruit enum set on it to indicate the type of fruit in the basket. The bean definition creates a FruitBasket and sets the fruit property with the value 'APPLE'. Spring looks up the matching enum value from the Fruit class and sets it on the property.

Excerpt from chapter03-collections/src/main/java/org/springbyexample/springindepth/chapter03/collections/Fruit.java
                    
/**
 * Enumeration of different types of fruit.
 */
public enum Fruit {

    APPLE, ORANGE, PEAR
    
}
                    
                
Excerpt from chapter03-collections/src/main/java/org/springbyexample/springindepth/chapter03/collections/FruitBasket.java
                   
/**
 * Sets fruit.
 */
public void setFruit(Fruit fruit) {
    this.fruit = fruit;
}
                    
                
Excerpt from chapter03-collections/src/main/resources/enum-applicationContext.xml
                    
<bean id="fruitBasket"
      class="org.springbyexample.springindepth.chapter03.collections.FruitBasket">
    <property name="fruit" value="APPLE"/>
</bean> 
                    
                

Example 3.31. Pre Java 5 Type-Safe Enums

This is example is almost identical to the Java 5 enum example except before Java 5 enums didn't exist. The enum class used is a type-safe emulated enum. It exposes type-safe constants on it representing different types of fruit and the constructor is private so no one can create other types of fruit for this class. The only other way to do this before Java 5 was to just use int constants, but this isn't type-safe in any way. Also any number could be passed into a method that takes an int.

Excerpt from chapter03-collections/src/main/java/org/springbyexample/springindepth/chapter03/collections/OldFruit.java
                    
/**
 * Pre Java 5 type-safe enumeration of different types of fruit.
 */
public class OldFruit {

    private String fruit = null;
    
    public final static OldFruit APPLE = new OldFruit("apple");
    public final static OldFruit ORANGE = new OldFruit("orange");
    public final static OldFruit PEAR = new OldFruit("pear");
    
    /**
     * Private constructor.
     */
    private OldFruit(String fruit) {
        this.fruit = fruit;
    }

    ...

}
                    
                
Excerpt from chapter03-collections/src/main/java/org/springbyexample/springindepth/chapter03/collections/OldFruitBasket.java
                   
/**
 * Sets old fruit.
 */
public void setFruit(OldFruit fruit) {
    this.fruit = fruit;
}
                    
                
Excerpt from chapter03-collections/src/main/resources/enum-applicationContext.xml
                    
<bean id="oldFruitBasket"
      class="org.springbyexample.springindepth.chapter03.collections.OldFruitBasket">
    <property name="fruit" value="APPLE"/>
</bean>