Saturday, October 13, 2012

Spring Collection Merging

Spring collection merging is a feature that I first came across as an answer to a StackOverflow question

It is a way of creating a base collection (list, set, map or properties) and modifying this base collection in other beans, best explained using an example -

Consider a Person class with a field holding a list of addresses:

public class Person {
 private List<Address> addresses;
..
}

Assume that all Person instances have a common set of addresses, which can be specified using an abstract person bean this way:

<bean name="basePerson" class="Person" abstract="true">
 <property name="addresses">
  <list>
   <bean class="Address" p:street="Street1" p:state="State1" p:zip="001"></bean>
   <bean class="Address" p:street="Street2" p:state="State2" p:zip="002"></bean>
   <bean class="Address" p:street="Street3" p:state="State3" p:zip="003"></bean>
  </list>
 </property>
</bean>

Now, Person bean instances with addresses in addition to the addresses from the basePerson can be specified using Collection Merging feature this way - note the "merge=true" attribute of list:

<bean name="person1" class="Person" parent="basePerson">
 <property name="addresses">
  <list merge="true">
   <bean class="Address" p:street="Street4" p:state="State4" p:zip="004"></bean>
  </list>
 </property>
</bean>

Collection merging also works with <set/>, <map/> and <props/>

With Spring 3.1 and higher, a simpler option though could be simply to use @Configuraion and @Bean options, as then the merging can be directly handled with Java code, for eg, an equivalent @Configuration for the above xml bean configuration:

@Configuration
public class CollectionConfig{
 
 private List<Address> baseAddresses(){
  return Lists.newArrayList(new Address("Street1", "State1", "001"), new Address("Street2", "State2", "002"), new Address("Street3", "State3", "003"));
 }
 
 
 @Bean
 public Person person1(){
  Person person1 = new Person();
  person1.setAddresses(baseAddresses());
  person1.getAddresses().add(new Address("Street4", "State4", "004"));
  return person1;
 }
}


1 comment: