Defining Collections for Bean Properties

List, Set, and Map are the core interfaces representing three main types of collections. For each collection type, Java provides several implementations with different functions and haracteristics from which you can choose. In Spring, these types of collections can be easily configured with a group of built-in XML tags, such as <list>, <set>, and <map>.

package com.sequence;
public class SequenceGenerator {
private List<Object> suffixes;
public void setSuffixes(List<Object> suffixes) {
this.suffixes = suffixes;
}
public synchronized String getSequence() {
StringBuffer buffer = new StringBuffer();
for (Object suffix : suffixes) {
buffer.append("-");
buffer.append(suffix);
}
return buffer.toString();
}
}

A list our bean would look something like:

<bean id="sequenceGenerator"
class="com.sequence.SequenceGenerator">
<property name="prefixGenerator" ref="datePrefixGenerator" />
<property name="initial" value="100000" />
<property name="suffixes">
<list>
<value>A</value>
<bean class="java.net.URL">
<constructor-arg value="http" />
<constructor-arg value="www.apress.com" />
<constructor-arg value="/" />
</bean>
<null />
</list>
</property>
</bean>

To define a property of java.util.Set type, use the <set> tag to define the elements in the same way as a list.

<bean id="sequenceGenerator"
class="com.sequence.SequenceGenerator">
<property name="suffixes">
<set>
<value>A</value>
<bean class="java.net.URL">
<constructor-arg value="http" />
<constructor-arg value="www.apress.com" />
<constructor-arg value="/" />
</bean>
<null />
</set>
</property>
</bean>

Example of your sequence generator to accept a java.util.Map collection that contains suffixes with keys.

package com.sequence;
public class SequenceGenerator {
private Map<Object, Object> suffixes;
public void setSuffixes(Map<Object, Object> suffixes) {
this.suffixes = suffixes;
}
public synchronized String getSequence() {
StringBuffer buffer = new StringBuffer();
for (Map.Entry entry : suffixes.entrySet()) {
buffer.append("-");
buffer.append(entry.getKey());
buffer.append("@");
buffer.append(entry.getValue());
}
return buffer.toString();
}
}

In Spring, a map is defined by the <map> tag, with multiple <entry> tags as children. Each entry contains a key and a value. The key must be defined inside the <key> tag. There is no restriction on the type of the key and value, so you are free to specify a <value>, <ref>, <bean>, or <null> element for them. Spring will also preserve the order of the map entries by using java.util.LinkedHashMap.

<bean id="sequenceGenerator"
class="com.sequence.SequenceGenerator">
<property name="suffixes">
<map>
<entry>
<key>
<value>type</value>
</key>
<value>A</value>
</entry>
<entry>
<key>
<value>url</value>
</key>
<bean class="java.net.URL">
<constructor-arg value="http" />
<constructor-arg value="www.apress.com" />
<constructor-arg value="/" />
</bean>
</entry>
</map>
</property>
</bean>

A shortcut to the above bean:

<bean id="sequenceGenerator"
class="com.sequence.SequenceGenerator">
<property name="suffixes">
<map>
<entry key="type" value="A" /> <entry
key="url">
<bean class="java.net.URL">
<constructor-arg value="http" />
<constructor-arg value="www.apress.com" />
<constructor-arg value="/" />
</bean>
</entry>
</map>
</property>
</bean>

A java.util.Properties collection is very similar to a map. It also implements the java.util.Map interface and stores entries in key/value pairs. The only difference is that the keys and values of a Properties collection are always strings.

package com.sequence;
public class SequenceGenerator {
private Properties suffixes;
public void setSuffixes(Properties suffixes) {
this.suffixes = suffixes;
}
}

To define a java.util.Properties collection in Spring, use the <props> tag with multiple <prop> tags as children. Each <prop> tag must have a key attribute defined and the corresponding value enclosed.

<bean id="sequenceGenerator"
class="com.sequence.SequenceGenerator">
<property name="suffixes">
<props>
<prop key="type">A</prop>
<prop key="url">http://www.apress.com/</prop>
</props>
</property>
</bean>

Merging the Collection of the Parent Bean

If you define your beans with inheritance, a child bean’s collection can be merged with that of its parent by setting the merge attribute to true. For a <list> collection, the child elements will be appended after the parent’s to preserve the order. So, the following sequence generator will have four suffixes: A, B, A, and C.

<beans …>
<bean id="baseSequenceGenerator"
class="com.sequence.SequenceGenerator">
<property name="prefixGenerator" ref="datePrefixGenerator" />
<property name="initial" value="100000" />
<property name="suffixes">
<list>
<value>A</value>
<value>B</value>
</list>
</property>
</bean>
<bean id="sequenceGenerator" parent="baseSequenceGenerator">
<property name="suffixes">
<list merge="true">
<value>A</value>
<value>C</value>
</list>
</property>
</bean>
</beans>

For a <set> or <map> collection, the child elements will overwrite the parent’s if they have the same value. So, the following sequence generator will have three suffixes: A, B, and C.

<beans …>
<bean id="baseSequenceGenerator"
class="com.sequence.SequenceGenerator">
<property name="prefixGenerator" ref="datePrefixGenerator" />
<property name="initial" value="100000" />
<property name="suffixes">
<set>
<value>A</value>
<value>B</value>
</set>
</property>
</bean>
<bean id="sequenceGenerator" parent="baseSequenceGenerator">
<property name="suffixes">
<set merge="true">
<value>A</value>
<value>C</value>
</set>
</property>
</bean>
</beans>