Spring – Injecting Collections

1. Introduction

In this tutorial, we’re going to show how to inject Java collections using the Spring framework.

Simply put, we’ll demonstrate examples with the List, Map, Set collection interfaces.

2. List With @Autowired

Let’s create an example bean:

public class CollectionsBean {

    @Autowired
    private List<String> nameList;

    public void printNameList() {
        System.out.println(nameList);
    }
}

Here, we declared the nameList property to hold a List of String values.

In this example, we use field injection for nameList. Therefore, we put the @Autowired annotation.

To learn more about the dependency injection or different ways to implement it, check out this guide.

After, we register the CollectionsBean in the configuration setup class:

@Configuration
public class CollectionConfig {

    @Bean
    public CollectionsBean getCollectionsBean() {
        return new CollectionsBean();
    }

    @Bean
    public List<String> nameList() {
        return Arrays.asList("John", "Adam", "Harry");
    }
}

Besides registering the CollectionsBean, we also inject a new list by explicitly initializing and returning it as a separate @Bean configuration.

Now, we can test the results:

ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class);
CollectionsBean collectionsBean = context.getBean(
  CollectionsBean.class);
collectionsBean.printNameList();

The output of printNameList() method:

[John, Adam, Harry]

3. Set With Constructor Injection

To set up the same example with the Set collection, let’s modify the CollectionsBean class:

public class CollectionsBean {

    private Set<String> nameSet;

    public CollectionsBean(Set<String> strings) {
        this.nameSet = strings;
    }

    public void printNameSet() {
        System.out.println(nameSet);
    }
}

This time we want to use a constructor injection for initializing the nameSet property. This requires also changes in configuration class:

@Bean
public CollectionsBean getCollectionsBean() {
    return new CollectionsBean(new HashSet<>(Arrays.asList("John", "Adam", "Harry")));
}

4. Map With Setter Injection

Following the same logic, let’s add the nameMap field to demonstrate the map injection:

public class CollectionsBean {

    private Map<Integer, String> nameMap;

    @Autowired
    public void setNameMap(Map<Integer, String> nameMap) {
        this.nameMap = nameMap;
    }

    public void printNameMap() {
        System.out.println(nameMap);
    }
}

This time we have a setter method in order to use a setter dependency injection. We also need to add the Map initializing code in configuration class:

@Bean
public Map<Integer, String> nameMap(){
    Map<Integer, String>  nameMap = new HashMap<>();
    nameMap.put(1, "John");
    nameMap.put(2, "Adam");
    nameMap.put(3, "Harry");
    return nameMap;
}

The results after invoking the printNameMap() method:

{1=John, 2=Adam, 3=Harry}

5. Injecting Bean References

Let’s look at an example where we inject bean references as elements of the collection.

First, let’s create the bean:

public class VietMXBean {

    private String name;

    // constructor
}

And add a List of VietMXBean as a property to the CollectionsBean class:

public class CollectionsBean {

    @Autowired(required = false)
    private List<VietMXBean> beanList;

    public void printBeanList() {
        System.out.println(beanList);
    }
}

Next, we add the Java configuration factory methods for each VietMXBean element:

@Configuration
public class CollectionConfig {

    @Bean
    public VietMXBean getElement() {
        return new VietMXBean("John");
    }

    @Bean
    public VietMXBean getAnotherElement() {
        return new VietMXBean("Adam");
    }

    @Bean
    public VietMXBean getOneMoreElement() {
        return new VietMXBean("Harry");
    }

    // other factory methods
}

The Spring container injects the individual beans of the VietMXBean type into one collection.

To test this, we invoke the collectionsBean.printBeanList() method. The output shows the bean names as list elements:

[John, Harry, Adam]

Now, let’s consider a scenario when there is not a VietMXBean. If there isn’t a VietMXBean registered in the application context, Spring will throw an exception because the required dependency is missing.

We can use @Autowired(required = false) to mark the dependency as optional. Instead of throwing an exception, the beanList won’t be initialized and its value will stay null.

If we need an empty list instead of null, we can initialize beanList with a new ArrayList:

@Autowired(required = false)
private List<VietMXBean> beanList = new ArrayList<>();

5.1. Using @Order to Sort Beans

We can specify the order of the beans while injecting into the collection.

For that purpose, we use the @Order annotation and specify the index:

@Configuration
public class CollectionConfig {

    @Bean
    @Order(2)
    public VietMXBean getElement() {
        return new VietMXBean("John");
    }

    @Bean
    @Order(3)
    public VietMXBean getAnotherElement() {
        return new VietMXBean("Adam");
    }

    @Bean
    @Order(1)
    public VietMXBean getOneMoreElement() {
        return new VietMXBean("Harry");
    }
}

Spring container first will inject the bean with the name “Harry”, as it has the lowest order value.

It will then inject the “John”, and finally, the “Adam” bean:

[Harry, John, Adam]

Learn more about @Order in this guide.

5.2. Using @Qualifier to Select Beans

We can use the @Qualifier to select the beans to be injected into the specific collection that matches the @Qualifier name.

Here’s how we use it for the injection point:

@Autowired
@Qualifier("CollectionsBean")
private List<VietMXBean> beanList;

Then, we mark with the same @Qualifier the beans that we want to inject into the List:

@Configuration
public class CollectionConfig {

    @Bean
    @Qualifier("CollectionsBean")
    public VietMXBean getElement() {
        return new VietMXBean("John");
    }

    @Bean
    public VietMXBean getAnotherElement() {
        return new VietMXBean("Adam");
    }

    @Bean
    public VietMXBean getOneMoreElement() {
        return new VietMXBean("Harry");
    }

    // other factory methods
}

In this example, we specify that the bean with the name “John” will be injected into the List named “CollectionsBean”. The results we test here:

ApplicationContext context = new AnnotationConfigApplicationContext(CollectionConfig.class);
CollectionsBean collectionsBean = context.getBean(CollectionsBean.class);
collectionsBean.printBeanList();

From the output, we see that our collection has only one element:

[John]

6. Setting an Empty List as a Default Value

We can set the default value for an injected List property as an empty list by using the Collections.emptyList() static method:

public class CollectionsBean {

    @Value("${names.list:}#{T(java.util.Collections).emptyList()}")
    private List<String> nameListWithDefaultValue;
    
    public void printNameListWithDefaults() {
        System.out.println(nameListWithDefaultValue);
    }
}

If we run this with the “names.list” key not initialized via properties file:

collectionsBean.printNameListWithDefaults();

We’ll get an empty list as output:

[ ]

7. Summary

With this guide, we learned how to inject different types of Java collections using the Spring framework.

We also examined injection with reference types and how to select or order them inside of the collection.

As usual, the complete code is available in the GitHub project.

Related posts:

Object cloning trong java
Spring 5 and Servlet 4 – The PushBuilder
Java Program to Find Strongly Connected Components in Graphs
ClassNotFoundException vs NoClassDefFoundError
OAuth2 for a Spring REST API – Handle the Refresh Token in Angular
Java Program to do a Depth First Search/Traversal on a graph non-recursively
Iterating over Enum Values in Java
RestTemplate Post Request with JSON
Java Program for Douglas-Peucker Algorithm Implementation
Upload and Display Excel Files with Spring MVC
Java Program to Construct K-D Tree for 2 Dimensional Data
The StackOverflowError in Java
Hướng dẫn Java Design Pattern – Iterator
Java Program to subtract two large numbers using Linked Lists
Java Program to Represent Graph Using Adjacency Matrix
Java Program to Implement EnumMap API
Java Program to Implement a Binary Search Algorithm for a Specific Search Sequence
REST Web service: Upload và Download file với Jersey 2.x
Get the workstation name or IP
Guide to java.util.concurrent.Future
Java Program to Perform Polygon Containment Test
Java Program to Find Minimum Element in an Array using Linear Search
Một số nguyên tắc, định luật trong lập trình
Java Program to Implement the Binary Counting Method to Generate Subsets of a Set
Java Map With Case-Insensitive Keys
Java Program to Check whether Directed Graph is Connected using BFS
Working With Maps Using Streams
Java Program to Implement Cubic convergence 1/pi Algorithm
The HttpMediaTypeNotAcceptableException in Spring MVC
A Guide to BitSet in Java
Các chương trình minh họa sử dụng Cấu trúc điều khiển trong Java
Java Program to Implement First Fit Decreasing for 1-D Objects and M Bins