How do I create a projection of a collection using Spring EL?

In this example you will learn how to create a projection of a collection object. Using projection we can create a new collection with only a specific property from the original collection.

As an example, instead of returning a collection of Book objects we would like only to have the titles of the books. To do this we can use the Spring EL projection operator. The symbol use for this operator is ![].

Let’s begin by creating the Spring configuration file:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <util:list id="books">
        <bean class="org.kodejava.spring.core.el.Book" p:title="Essential C# 4.0" p:author="Michaelis" p:pages="450" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="User Stories Applied" p:author="Mike Cohen"
              p:pages="268" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Learning Android" p:author="Marco Gargenta"
              p:pages="245" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="The Ruby Programming Language"
              p:author="David Flanagan & Yukihiro Matsumoto" p:pages="250" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Einstein" p:author="Walter Isaacson" p:pages="1000" />
    </util:list>

    <bean id="library" class="org.kodejava.spring.core.el.Library">
        <property name="bookTitles" value="#{books.![title]}" />
    </bean>

</beans>

Here are the definition of the Book and Library class. The getters and setters methods were removed for simplicity of the snippet.

package org.kodejava.spring.core.el;

public class Book {
    private Long id;
    private String title;
    private String author;
    private String type;
    private int pages;

    // Getters & Setters
}
package org.kodejava.spring.core.el;

import java.util.List;

public class Library {
    private List<Book> books;
    private List<String> bookTitles;

    // Getters & Setters
}

Now, let’s talk about the Spring configuration above. The configuration was start by creating a collection of Books using the <util:elements>. The part that use the projection operator is this part of the configuration:

<bean id="library" class="org.kodejava.spring.core.el.Library">
    <property name="bookTitles" value="#{books.![title]}"/>
</bean>

The bean element above create a library bean of type org.kodejava.spring.core.el.Library. We assign the bean’s bookTitles property with values that are a projection of the books collection where we take only the title of the books. ![projectionExpression] is the syntax of the projection operator.

The code snippet below will demonstrate and run our configuration file and print out the result:

package org.kodejava.spring.core.el;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpELProjectionExample {
    public static void main(String[] args) {
        try (ClassPathXmlApplicationContext context =
                     new ClassPathXmlApplicationContext("spel-projection.xml")) {

            Library library = context.getBean("library", Library.class);

            for (String title : library.getBookTitles()) {
                System.out.println("title = " + title);
            }
        }
    }
}

And here are the result:

title = Essential C# 4.0
title = User Stories Applied
title = Learning Android
title = The Ruby Programming Language
title = Einstein

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

Maven Central Maven Central Maven Central

How do I filter collection members based on some criteria using Spring EL?

In previous examples you have seen that we use the square-braces [] operator to select items from collection. In this post you will learn how to filter members of a collection with a certain criteria using the Spring EL. To do this Spring EL give you another special operator, the filter operator which can be typed like .?[], you can define the filter criteria inside the braces.

Beside the filter operator .?[] there are also operator that can select the first and the last matching items from collection. You can use the .^[] for selecting the first match and the .$[] operator to select the last match items from collection respectively.

As an example we will demonstrate here that we want to find a collection of books that have pages more than 250 and assign it to Library bean’s books properties. So let’s begin by defining a class called Book and Library which will have the following properties:

package org.kodejava.spring.core.el;

public class Book {
    private Long id;
    private String title;
    private String author;
    private String type;
    private int pages;

    // Getters & Setters

    @Override
    public String toString() {
        return "Book{" +
                "title='" + title + '\'' +
                ", author='" + author + '\'' +
                ", pages=" + pages +
                '}';
    }
}
package org.kodejava.spring.core.el;

import java.util.List;

public class Library {
    private List<Book> books;

    public List<Book> getBooks() {
        return books;
    }

    public void setBooks(List<Book> books) {
        this.books = books;
    }
}

After creating the Book and the Library class let’s now create the Spring configuration file for our demo. We will create a file and call it as spel-filter-collection.xml with the following lines of configuration in it.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <util:list id="books">
        <bean class="org.kodejava.spring.core.el.Book" p:title="Essential C# 4.0" p:author="Michaelis" p:pages="450" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="User Stories Applied" p:author="Mike Cohen"
              p:pages="268" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Learning Android" p:author="Marco Gargenta"
              p:pages="245" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="The Ruby Programming Language"
              p:author="David Flanagan & Yukihiro Matsumoto" p:pages="250" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Einstein" p:author="Walter Isaacson" p:pages="1000" />
    </util:list>

    <bean id="lib1" class="org.kodejava.spring.core.el.Library">
        <property name="books" value="#{books.?[pages gt 250]}" />
    </bean>

    <bean id="lib2" class="org.kodejava.spring.core.el.Library">
        <property name="books" value="#{books.^[pages gt 250]}" />
    </bean>

    <bean id="lib3" class="org.kodejava.spring.core.el.Library">
        <property name="books" value="#{books.$[pages gt 250]}" />
    </bean>

</beans>

The first thing that you can see in the configuration above is the <util-list> where we create a list of Book beans. Next we have three beans definition of the type Library where the books property was assigned with a collection of beans selected from the books list.

The lib1 will contains books that have pages more than 250. The lib2 will contains the first book found to have more than 250 pages while the lib3 will contains the last book found to have more than 250 pages.

Below is the code that will run our configuration file and the example output it will produce.

package org.kodejava.spring.core.el;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpELFilterCollection {
    public static void main(String[] args) {
        try (ClassPathXmlApplicationContext context =
                     new ClassPathXmlApplicationContext("spel-filter-collection.xml")) {

            System.out.println("Library 1");
            Library lib1 = (Library) context.getBean("lib1");
            for (Book book : lib1.getBooks()) {
                System.out.println("    Book = " + book);
            }

            System.out.println("Library 2");
            Library lib2 = (Library) context.getBean("lib2");
            for (Book book : lib2.getBooks()) {
                System.out.println("    Book = " + book);
            }

            System.out.println("Library 3");
            Library lib3 = (Library) context.getBean("lib3");
            for (Book book : lib3.getBooks()) {
                System.out.println("    Book = " + book);
            }
        }
    }
}
Library 1
    Book = Book{title='Essential C# 4.0', author='Michaelis', pages=450}
    Book = Book{title='User Stories Applied', author='Mike Cohen', pages=268}
    Book = Book{title='Einstein', author='Walter Isaacson', pages=1000}
Library 2
    Book = Book{title='Essential C# 4.0', author='Michaelis', pages=450}
Library 3
    Book = Book{title='Einstein', author='Walter Isaacson', pages=1000}

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

Maven Central Maven Central Maven Central

How do I access collections members using Spring EL?

In this post you will see another powerful examples of Spring EL. We are going to demonstrate how to use Spring EL to access collection members.

By using Spring EL you can select a single reference member of a collection. You can also select members of collection based on the values of their properties. Another thing you can do is extract properties out of the collection members to create another collection object.

To demonstrate this we are going to create a simple bean / pojo as our collection object. We will create a Book class with some properties (id, title, author).

package org.kodejava.spring.core.el;

public class Book {
    private Long id;
    private String title;
    private String author;
    private String type;

    // Getters & Setters
}

Next, we need to create the spring configuration file. In this configuration we will create a collection of books using the <util:list> element. And we also create a bean with its properties is obtained from one of the collection objects.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd">

    <util:list id="books">
        <bean class="org.kodejava.spring.core.el.Book" p:title="Essential C# 4.0" p:author="Michaelis" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="User Stories Applied" p:author="Mike Cohen" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Learning Android" p:author="Marco Gargenta" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="The Ruby Programming Language"
              p:author="David Flanagan & Yukihiro Matsumoto" />
        <bean class="org.kodejava.spring.core.el.Book" p:title="Einstein" p:author="Walter Isaacson" />
    </util:list>

    <bean id="book" class="org.kodejava.spring.core.el.Book">
        <property name="title" value="#{books[3].title}" />
        <property name="author" value="#{books[3].author}" />
    </bean>

</beans>

In the configuration above you have seen how we set the title and author of the book bean. We use the square-braces operator ([]) to access collection’s member by their index. It’s look like this:

<property name="title" value="#{books[3].title}"/>
<property name="author" value="#{books[3].author}"/>

Which can be read as: please give me the collection object at index number 3 and take the value of its title and author to be assigned to the book bean. And as you might already know that a collection object in Java is always zero-based index. So this will give us the book with title “The Ruby Programming Language”.

And finally let’s create an example class that run our spring configuration above. It’s simply load the spell-collection.xml configuration we create above. Get a bean from the loaded ApplicationContext and print out its properties, title and author properties.

package org.kodejava.spring.core.el;

import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpELCollectionExample {
    public static void main(String[] args) {
        try (ClassPathXmlApplicationContext context =
                     new ClassPathXmlApplicationContext("spel-collection.xml")) {

            Book book = (Book) context.getBean("book");
            System.out.println("book.getTitle() = " + book.getTitle());
            System.out.println("book.getAuthor() = " + book.getAuthor());
        }
    }
}

Executing the code above will give you the following result:

book.getTitle() = The Ruby Programming Language
book.getAuthor() = David Flanagan & Yukihiro Matsumoto

Maven Dependencies

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-core</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>5.3.23</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.23</version>
    </dependency>
</dependencies>

Maven Central Maven Central Maven Central

How do I create a generic Map object?

In this example of Java Generics you will see how to create a generic Map object. Creating a generic Map means that you can define the type of the key and the type of the value of object stored in the Map. The declaration and the instantiation of a generic Map is only different to other type of collection such as List and Set is that we to define two types. One type for the key and the other type for the value.

The syntax for creating a generic Map is as follows:

Map<K, V> map = new Map<K, V>();

Where K is the type of map key and V is the type of the value stored in the map. If you want a map to hold a value of reference to String object and using an Integer as the key, you will write the declaration and instantiation like the snippet below.

Map <Integer, String> map = new HashMap<Integer, String>();

To make it simpler, you can use the diamond operator too.

Map <Integer, String> map = new HashMap<>();

When you want to add some elements to the map you can use the same put() method. But you don’t have to worry that you put a wrong type of object into the map. Because the Java compiler will check it to see if you are storing a correct type. Generic will catch the bug that should not happen at runtime because the code is already validated at compile time.

Map <Integer, String> map = new HashMap<>();
map.put(1, "A");
map.put(2, "B");
map.put(3, "C");

//map.put("4", new Date()); // Compile time error!  

String a = map.get(1);
String b = map.get(2);
String c = map.get(3);

The get() method will return a value from the map that correspond with the given key. Because the map know that it store values of string, it will return a string. So you don’t need to cast the return value from the map’s get() method. You might wonder why we can put keys like 1, 2, 3. Doesn’t it supposed to be type of Integer? If you remember the auto boxing feature then you’ll understand this. Behind the screen Java will convert the primitive int to Integer.

Now, after we know how to add elements and read it back from the map. Let iterate the contents of the map. A map will have two collections that you can iterate, the keys and the values. The code snippet below will demonstrate it for you. The first snippet show you how the iterate the map using the key collections while the second iterates the values of the map.

Iterate key collections.

Iterator keyIterator = map.keySet().iterator();
while (keyIterator.hasNext()) {
    Integer key = keyIterator.next();
    String value = map.get(key);
    System.out.println("key = " + key + "; value = " + value);
}

When iterating a map using the key collection you will get the key set of the map and check the hasNext() to see if it has next key. After that you can get the key using the next() method. To get the value you call the get() method and pass the key as the argument.

Iterates value collections.

Iterator valueIterator = map.values().iterator();
while(valueIterator.hasNext()) {
    System.out.println("value = " + valueIterator.next());
}

If you want to iterate the value and ignoring the keys you can get the value collections from the map. To validate if it still holds more entries you call the hasNext() method. To obtain the value simply call the next() method from the iterator.

Notice that when using generic you don’t need to do any casting when working with generic map. Everything is added to map and read from the map is according the type of the key and the value of the map. Beside using the Iterator you can also use the for-each loop to iterate the map. Here are the version of the code above written using the for-each loop.

for (Integer key : map.keySet()) {
    String value = map.get(key);
    System.out.println("key = " + key + "; value = " + value);
}

for (String s : map.values()) {
    System.out.println("value = " + s);
}

You can choose either way that match your coding style. Both method of iterating the map object will produce the same result.

How do I create a generic Set?

In another post of Java Generics you have seen how to create a generic collection using List in this example you will learn how to make a generic Set. Making a Set generic means that we want it to only hold objects of the defined type. We can declare and instantiate a generic Set like the following code.

Set<String> colors = new HashSet<>();

We use the angle brackets to define the type. We need also to define the type in the instantiation part, but using the diamond operator remove the duplicate and Java will infer the type itself. This declaration and instantiation will give you a Set object that holds a reference to String objects. If you tried to ask it to hold other type of object such as Date or Integer you will get a compiled time error.

Set<String> colors = new HashSet<>();
colors.add("Red");
colors.add("Green");
colors.add("Blue");

//colors.add(new Date()); // Compile time error!

The code for adding items to a set is look the same with the old way we code. But again, one thing you will get here for free is that the compiler will check to see if you add the correct type to the Set. If we remove the remark on the last line from the snippet above we will get a compiled time error. Because we are trying to store a Date into a Set of type String.

Now, let see how we can iterate the contents of the Set. First we’ll do it using the Iterator. And here is the code snippet.

Iterator iterator = colors.iterator();
while (iterator.hasNext()) {
    System.out.println(iterator.next());
}

When using a generic Set it will know that the iterator.next() will return a type of String so that you don’t have use the cast operator. Which of course will make you code looks cleaner and more readable. We can also using the for-each loop when iterating the Set as can be seen in the following example.

for (String color : colors) {
    System.out.println(color);
}