Configuring Collection

The Collection framework in Java facilitates handling objects to perform various operations such as addition, removal, searching, and sorting of objects in a simplified way. Set, List, Map, and Queue, are the interfaces that have many implementations, such as HashSet, ArrayList, TreeMap, PriorityQueue, and many more, which gives a means to handle data. We will not go into detail on which one to choose for the operations, but we will discuss the different configurations supported by Spring in injecting Collection.

Mapping List

List is an ordered collection, which offers handling of data in the order of data insertion. It maintains the insertion, removal, and fetching of data by indices, where duplicate elements are allowed. ArrayList and LinkedList are some of its implementations. The framework supports List configuration with the help of the <list> tag. Let's develop an application to configure List by following these steps:

  1. Create Ch02_DI_Collection as a Java project, and add Spring jars to it.
  2. Create a POJO class Book in the com.ch02.beans package by following these steps:
    1. Add isbn, book_name, price, and publication as data members.
    2. Add default and parameterized constructors.
    3. Write the getter and setter methods.
    4. As we are handling collection, add equals() and hashCode().
    5. To display object, add toString().

The Book class will be as shown in the following piece of code:

public class Book { 
  private String isbn; 
  private String book_name; 
  private int price; 
  private String publication; 
 
  public Book() 
  { 
    isbn="310IND"; 
    book_name="unknown"; 
    price=300; 
    publication="publication1"; 
  } 
 
  public Book(String isbn, String book_name, int price, String
publication){ this.isbn=isbn; this.book_name=book_name; this.price=price; this.publication=publication; } @Override public String toString() { // TODO Auto-generated method stub return book_name+" "+isbn+" "+price+" "+publication; } @Override public boolean equals(Object object) { // TODO Auto-generated method stub Book book=(Book)object; return this.isbn.equals(book.getIsbn()); } public int hashCode() { return book_name.length()/2; } // getters and setters }
  1. Create Library_List in com.ch02.beans, which has a list of books. Write displayBooks() to display the list of books. The code will be as follows:
public class Library_List { 
  private List<Book>books; 
  public void displayBooks() 
  { 
    for(Book b:books) 
    { 
       System.out.println(b); 
    } 
  } 
  // add getter and setter for books 
} 
  1. Create books.xml in classpath. Add to it four Book beans. We have the following three configurations:
    • Book bean with setter DI
    • Book bean with constructor DI
    • Book bean using the p namespace

No need to try out all the combinations; you can follow any one of them. We have already used all of them in the previous demos. The configuration will be as follows:

<bean id="book1" class="com.ch02.beans.Book"> 
  <property name="isbn" value="20Novel"/> 
  <property name="book_name" value="princess Sindrella"/> 
  <property name="price" value="300"/> 
  <property name="publication" value="Packt-Pub"></property> 
</bean> 
 
<bean id="book2" class="com.ch02.beans.Book"> 
  <constructor-arg value="Java490"/> 
  <constructor-arg value="Core Java"/> 
  <constructor-arg value="300"/> 
  <constructor-arg value="Packt-Pub"/> 
</bean> 
 
<bean id="book3"class="com.ch02.beans.Book" 
    p:isbn="200Autobiography" 
    p:book_name="Playing it in my way" p:price="300" 
    p:publication="Packt-Pub"> 
</bean> 

Intentionally, the fourth book is the second copy of one of the first three books. In a couple of steps, we will discover the reason; just wait and watch!!

  1. Add a Library bean with the<list> configuration as follows:
<bean id="library_list"
class="com.ch02.beans.Library_List"> <property name="books"> <list> <ref bean="book1"></ref> <ref bean="book2"></ref> <ref bean="book3"></ref> <ref bean="book3"></ref> </list> </property> </bean>

The <list> parameter contains a list of <ref> of the beans to be injected for the list of books, where book1, book2, book3, and book4 are the IDs of the beans that we created in step 4.

  1. Create TestLibrary_List with the main function to get an instance of Library and the list of books that it has. The code is as follows:
public static void main(String[] args) { 
  // TODO Auto-generated method stub 
  ApplicationContext context=new 
      ClassPathXmlApplicationContext("books.xml"); 
  Library_List  list= 
(Library_List)context.getBean("library_list"); list.displayBooks(); }
  1. Execute it to get the following output displaying the list of books. Find the last two entries, which indicate the list that allows duplicate elements:

Mapping Set

The Set interface is an unordered collection, which doesn't allow duplicate entries in it. HashSet and TreeSet are the implementations of Set. Spring provides the<set> tag to configure Set. Let's use the Ch02_DI_Collection project to add a set of books by following these steps:

  1. Add a Library_Set class in the com.ch02.beans package, and declare Set of books as the data member. Add getters and setters for it. The code is as follows:
public class Library_Set { 
  HashSet<Book>books; 
 
  public void displayBooks() 
  { 
    for(Book b:books) 
    { 
       System.out.println(b); 
    } 
  } 
  //getter and setter for books 
} 
  1. Add a bean for Library_Set in beans.xml with the<set> configuration as follows:
<bean id="library_set" class="com.ch02.beans.Library_Set"> 
  <property name="books"> 
    <set> 
      <ref bean="book1"></ref> 
      <ref bean="book2"></ref> 
      <ref bean="book3"></ref> 
      <ref bean="book3"></ref> 
    </set> 
  </property> 
</bean> 
  1. Create TestLibrary_Set with the main function, as shown in the following piece of code:
public static void main(String[] args) { 
  // TODO Auto-generated method stub 
  ApplicationContext context=new 
     ClassPathXmlApplicationContext("books.xml"); 
  Library_Set set=     
     (Library_Set)context.getBean("library_set"); 
  set.displayBooks();      
} 
  1. The output of this execution is as follows:

We injected four objects of books, but got only three in output, so it's crystal clear that Set doesn't allow duplicates. Hope you got the point why we intentionally took only three book objects.

Mapping Map

Map handles a collection of objects having a key and value pair. It can have duplicate values, but duplicate keys are not allowed. It has implementations as TreeMap, HashMap, and LinkedHashMap.

Let's explore configuring Map with the help of the following steps:

  1. We will use the same Ch02_DI_Collection project. Create a class Library_Map in the com.ch02.beans package.
  2. Add Map<String,Book> books as a data member in it along with getters and setters. Don't forget to add displayBooks(). The code will be as follows:
public class Library_Map { 
  private Map<String,Book>books; 
 
  //getters and setters 
 
  public void displayBooks() 
  { 
    Set<Entry<String, Book>>entries=books.entrySet(); 
    for(Entry<String, Book>entry:entries) 
    { 
      System.out.println(entry.getValue()); 
    } 
  } 
} 
  1. Configure Map in beans.xml, as shown in the following piece of code:
<bean id="library_map" class="com.ch02.beans.Library_Map"> 
  <property name="books"> 
    <map> 
      <entry key="20Novel" value-ref="book1"/> 
      <entry key="200Autobiography" value-ref="book3"/> 
      <entry key="Java490" value-ref="book2"/> 
    </map> 
  </property> 
</bean> 

Unlike List and Set, Map will take an extra attribute of key to specify the key. Here, we used the name of the book as key, but if you want, you can declare something else as well. Just don't forget that key is always unique in Map.

  1. Write TestLibrary_Map with the main function as follows:
public static void main(String[] args) { 
  // TODO Auto-generated method stub 
  ApplicationContext context=new 
    ClassPathXmlApplicationContext("books.xml"); 
  Library_Map map= 
   (Library_Map)context.getBean("library_map"); 
  map.displayBooks(); 
} 
  1. Execute the code to get the book details displayed on the console.

Here, we will configure a single object as per entry. However, in practice, an entry may contain a List or Set of books. In such cases, instead of having <entry> with value-ref, the configuration will contain <entry> with <list>, as shown in the following piece of code:

<bean id="library_map1"      
    class="com.ch02.beans.Library_Map1"> 
<property name="books"> 
<map> 
    <entry key="20Novel"> 
      <list> 
        <ref bean="book1"></ref> 
        <ref bean="book1"></ref> 
      </list>  
    </entry> 
    <entry key="200Autobiography"> 
      <list> 
        <ref bean="book3"></ref> 
        <ref bean="book3"></ref> 
      </list> 
    </entry> 
  </map> 
</property> 
</bean> 

In the preceding configuration, each entry has a name of the book containing a <list> of books, which is, obviously, a Library of books. The complete code of Library_Map1.java and TestLibrary_Map1.java can be referred from Ch02_DI_Collection.

Mapping Properties

Properties also holds the collection of elements in key-value pairs, but, unlike Map, here the key and value both are of String types only. The Properties can be saved or read from stream.

Let's consider a country having multiple states as Properties. Follow these steps to find out how to configure Properties in beans.xml:

  1. Create a class Country in the com.ch02.beans package.
  2. Declare name, continent, and state_capital as data members. Add getters and setters as well. To display state capitals, add printCapital(). The code is shown as follows:
public class Country { 
  private String name; 
  private String continent; 
  private Properties state_capitals; 
 
  // getters and setter  
 
  public void printCapitals() 
  { 
    for(String state:state_capitals.stringPropertyNames()) 
    { 
      System.out.println(state+":	"+ 
        state_capitals.getProperty(state)); 
    } 
  } 
} 
  1. In books.xml, configure the definition of Country, as follows:
<bean id="country" class="com.ch02.beans.Country"> 
  <property name="name" value="India"></property> 
  <property name="continent" value="Asia"></property> 
  <property name="state_capitals"> 
    <props> 
      <prop key="Maharashtra">Mumbai</prop> 
      <prop key="Goa">Panji</prop> 
      <prop key="Punjab">Chandigad</prop> 
    </props>  
  </property> 
</bean> 

The state_capitals property contains the <props> configuration to hold the name of the state as key, and its capital as value.

  1. Write TestProperties with the main function having the following code:
public static void main(String[] args) { 
  // TODO Auto-generated method stub 
  ApplicationContext context=new 
    ClassPathXmlApplicationContext("books.xml"); 
  Country country=(Country)context.getBean("country"); 
  country.printCapitals();; 
} 
  1. The output will be as shown in the following screenshot:

Spring provides multiple ways for configuration. We just discussed one way of mapping a collection in an XML file, however, we do have one more way for configuration. The util namespace provides a means for the developers to configure collections in an XML file elegantly. Using the util namespace, one can configure List, Map,Set, and Properties. To use the util namespace, the schema has to be updated for the www.springframework.org/schema/util URI, as shown in the following screenshot:

The underlined lines have to be added for enabling the util namespace in the configuration.

Let's configure List using the util namespace as follows:

<bean id="library_list1" class="com.ch02.beans.Library_List"> 
  <property name="books"> 
   <util:list> 
     <ref bean="book1"></ref> 
     <ref bean="book2"></ref> 
     <ref bean="book3"></ref> 
   </util:list> 
  </property> 
</bean> 

You can find the updated configuration in books.xml.

Now we know how to get the bean, and how to fulfill the different types of dependencies it has. The bean configuration defines the way in which instances are created, and its state is defined by injecting the dependencies. At any point of time, for business logic requirement, the state of bean can be changed. However, we don't know yet how many instances the Spring container creates, or what if developers want a single instance to serve every request? What if every operation needs different instances? Actually, we are talking about scope.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.117.196.184