11.1 Overview
We often need to define a properties of type collections like map, set, list etc in our java beans. Spring provides a convenient way to inject the collections in our beans.
In this chapter we will continue our discussion on dependency injection to understand how to inject inner beans and collections like map, list etc
11.2 Injecting Collections
Spring framework provides four type of collection ( <list>, <set>, <map> and <props>) element to configure the collections.
11.2.1 <list>
This element is used to wire a list of values and is used for List and Arrays type of objects in java. Since list and arrays allows duplicates, so the duplicates are supported in <list> tag also. This tag can be used for both simple types and beans .
List of simple types can be defined as
<bean id="country" class="Country"> <property name="states_name"> <list> <value>State 1</value> <value>State 2</value> <value>State 3</value> <value>State 4</value> </list> </property> </bean>
Above tag is equivalent to
- List<String> states_name
- String[] states_name
Similarly list of beans can be configured using <ref> child element instead of <value> like below
<bean id="country" class="Country"> <property name="states_name"> <list> <ref bean="State1" /> <ref bean="State2" /> <ref bean="State3" /> <ref bean="State4" /> </list> </property> </bean>
Above tag is equivalent to
- List<State> states_name
- State[] states_name
Where all 4 beans are of type custom bean “State”
11.2.2 <set>
This element is used to wire a list of values and is used for Set type in java. Since set does allows duplicates, so the duplicates are not supported in <set> tag also. This tag can be used for both simple types and beans .
List of simple types can be defined as
<bean id="country" class="Country"> <property name="states_name"> <set> <value>State 1</value> <value>State 2</value> <value>State 3</value> <value>State 4</value> </set> </property> </bean>
Above tag is equivalent to
- Set<String> states_name
Similarly list of beans can be configured using <ref> child element instead of <value> like below
<bean id="country" class="Country"> <property name="states_name"> <set> <ref bean="State1" /> <ref bean="State1" /> <ref bean="State3" /> <ref bean="State4" /> </set> </property> </bean>
Above tag is equivalent to
- Set<State> states_name
Where all 4 beans are of type custom bean “State” .
Above state_name set will contain 3 elements as State1 bean is added twice(highlighted above) . By default all the beans are defined in a singleton scope two beans referring State1 are same and set does not allows duplicates.
11.2.3 <map>
This element is used to wire a key-value pair and used for java.util.Map type in java.
In Maps, key and values can be of simple types and can be of object types so <map> tag also support both simple type and beans at both key and value level.
Elements supported by <map> tag are
- <key> - to define a key of simple type
- <key-ref> - to define a key referring to a bean
- <value> - to define simple type values
- <value-ref> - to define values referring to a bean
Map of simple types can be defined as
<bean id="country" class="Country"> <property name="states_name"> <map> <entry key="state1" value="State 1" /> <entry key="state2" value="State 2" /> <entry key="state3" value="State 3" /> <entry key="state4" value="State 4" /> </map> </property> </bean>
Above tag is equivalent to
- Map<String,String> states_name
Similarly map of beans (both key and values as beans) can be configured ike below
<bean id="country" class="Country"> <property name="states_name"> <map> <entry key-ref="state1" value-ref="State1" /> <entry key-ref="state2" value-ref="State2" /> <entry key-ref="state3" value-ref="State3" /> <entry key-ref="state4" value-ref="State4” /> </map> </property> </bean>
Above tag is equivalent to
- Map<State,State> states_name
Where all 4 beans are of type custom bean “State” .
<key> and <key-ref> can be used with both <value> and <value-ref>
11.2.4 <props> -
This element is used to define a java.util.Properties to wire a key-value pair similar to map with the only difference is that both key and value can be of type String only.
<bean id="country" class="Country"> <property name="states_name"> <props> <prop key="state1">State 1</prop> <prop key="state2">State 2</prop> <prop key="state3">State 3 </prop> <prop key="state4">State 4</prop> </props> </property> </bean>
11.3 Examples
11.3.1-
Lets write an example to use <list> and <set> tag for both simple and ref types
Solution – As any Country can have multiple states, lets write a Country class that contains list of States , set of States and list of states name. State class will have state name and code
- Write a State Class as below
public class State { private String name; private String countryCode; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getCountryCode() { return countryCode; } public void setCountryCode(String countryCode) { this.countryCode = countryCode; } @Override public String toString() { return "State [name=" + name + ", countryCode=" + countryCode + "]"; } }
b. Write a Country class as below
import java.util.List; import java.util.Set; public class Country { private List<String> statesName ; private List<State> statesList ; private Set<State> statesSet ; public List<String> getStatesName() { return statesName; } public void setStatesName(List<String> statesName) { this.statesName = statesName; } public List<State> getStatesList() { return statesList; } public void setStatesList(List<State> statesList) { this.statesList = statesList; } public Set<State> getStatesSet() { return statesSet; } public void setStatesSet(Set<State> statesSet) { this.statesSet = statesSet; } }
c. Define beans.xml with below beans configurations.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="State1" class="State"> <property name="name" value="United States" /> <property name="countryCode" value="+1" /> </bean> <bean id="State2" class="State"> <property name="name" value="United Kingdom" /> <property name="countryCode" value="+44" /> </bean> <bean id="State3" class="State"> <property name="name" value="India" /> <property name="countryCode" value="+91" /> </bean> <bean id="country" class="Country"> <property name="statesName"> <list> <value>United States</value> <value>United Kingdom</value> <value>India</value> </list> </property> <property name="statesList"> <list> <ref bean="State1" /> <ref bean="State1" /> <ref bean="State2" /> <ref bean="State3" /> </list> </property> <property name="statesSet"> <set> <ref bean="State1" /> <ref bean="State1" /> <ref bean="State2" /> <ref bean="State3" /> </set> </property> </bean> </beans>
- Write a TestCollection to test the program
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestCollection { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Country country = (Country)context.getBean("country"); System.out.println(country.getStatesName()); System.out.println(country.getStatesList()); System.out.println(country.getStatesSet()); } }
- Run the program – You will see below output. We can see there are four states in states list but three states in states set displayed because beans are singleton and set does not support duplicates
11.3.2 Lets write an example to use <map> tag
Solution – As any Bank can have multiple accounts , lets write a Bank class that contains map of Accounts. Account number will be used as a key and Account object as a value. Account class will have account holder name and balance in account. Also bank will have a map of String to store the weekly timings . Key of this timings map will be a day name and value will be the timings.
- Write a Account Class as below
public class Account { private String holderName ; private String balance ; public String getHolderName() { return holderName; } public void setHolderName(String holderName) { this.holderName = holderName; } public String getBalance() { return balance; } public void setBalance(String balance) { this.balance = balance; } @Override public String toString() { return "Account [holderName=" + holderName + ", balance=" + balance + "]"; } }
- Write a Bank class as below
import java.util.Map; public class Bank { private String name; private Map<String,Account> accounts private Map<String,String> timings ; public String getName() { return name; } public void setName(String name) { this.name = name; } public Map<String, Account> getAccounts() { return accounts; } public void setAccounts(Map<String, Account> accounts) { this.accounts = accounts; } public Map<String, String> getTimings() { return timings; } public void setTimings(Map<String, String> timings) { this.timings = timings; } }
- Define beans.xml with below beans configurations.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="Account1" class="Account"> <property name="holderName" value="Joe"></property> <property name="balance" value="$1200"></property> </bean> <bean id="Account2" class="Account"> <property name="holderName" value="Bloggs"></property> <property name="balance" value="$2200"></property> </bean> <bean id="Account3" class="Account"> <property name="holderName" value="Gary"></property> <property name="balance" value="$1800"></property> </bean> <bean id="bank" class="Bank"> <property name="name" value="My Bank Name"/> <property name="timings"> <map> <entry key="Monday" value="8:00 AM to 5:00 PM"/> <entry key="Tuesday" value="8:00 AM to 5:00 PM"/> <entry key="Wednesday" value="9:00 AM to 6:00 PM"/> <entry key="Thursday" value="9:00 AM to 5:00 PM"/> <entry key="Friday" value="9:00 AM to 5:00 PM"/> <entry key="Saturday" value="9:00 AM to 1:00 PM"/> <entry key="Sunday" value="Holiday"/> </map> </property> <property name="accounts"> <map> <entry key="account1" value-ref="Account1"/> <entry key="account2" value-ref="Account2"/> <entry key="account3" value-ref="Account3"/> </map> </property> </bean> </beans>
- Write a TestMapCollection to test the program
import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestMapCollection { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); Bank bank = (Bank)context.getBean("bank"); System.out.println("Bank Name :" + bank.getName()); System.out.println("Bank Timings :" + bank.getTimings()); System.out.println("Bank Accounts :" + bank.getAccounts()); } }
- Run the program – You will see below output.
11.3.3 Write an example to use <props> tag
Solution – Properties are key value pair with both are type String. Lets write a DataSource class which will have a properties object to contain database properties.
f. Write a DataSource Class as below
import java.util.Properties; public class DataSource { private Properties dbProperties; public Properties getDbProperties() { return dbProperties; } public void setDbProperties(Properties dbProperties) { this.dbProperties = dbProperties; } }
- Define beans.xml with below beans configurations.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="datasource" class="DataSource"> <property name="dbProperties"> <props> <prop key="username">root</prop> <prop key="password"></prop> <prop key="host">localhost</prop> <prop key="port">3306</prop> </props> </property> </bean> </beans>
- Write a TestPropsCollection to test the program
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <bean id="datasource" class="DataSource"> <property name="dbProperties"> <props> <prop key="username">root</prop> <prop key="password"></prop> <prop key="host">localhost</prop> <prop key="port">3306</prop> </props> </property> </bean> </beans>
- Run the program – You will see below output.