Saturday, July 6, 2024

Spring MVC - Binding List of Objects Example

In this post we’ll see how to bind a list of objects in Spring MVC so that the objects in that List can be displayed in the view part or to add to an ArrayList by binding object properties in view.

Spring MVC Project structure using Maven


Maven Dependencies

This example uses Spring 6 which uses Jakarta EE 9+ (in the jakarta namespace). JSTL tags are also used in this Spring MVC example for binding list of objects so you need to add Maven dependency for JSTL apart from Spring dependencies. Here only properties and dependencies section is given.

<properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>17</maven.compiler.source>
  <maven.compiler.target>17</maven.compiler.target>
  <spring.version>6.1.10</spring.version>
</properties>

<dependencies>
    <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-core</artifactId>
     <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-webmvc</artifactId>
      <version>${spring.version}</version>
  </dependency>
  <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <version>${spring.version}</version>
  </dependency>
<!-- https://mvnrepository.com/artifact/jakarta.servlet.jsp.jstl/jakarta.servlet.jsp.jstl-api -->
<dependency>
    <groupId>jakarta.servlet.jsp.jstl</groupId>
    <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
    <groupId>org.glassfish.web</groupId>
    <artifactId>jakarta.servlet.jsp.jstl</artifactId>
    <version>3.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/jstl/jstl -->
<dependency>
    <groupId>jstl</groupId>
    <artifactId>jstl</artifactId>
    <version>1.2</version>
</dependency>

  <!--<dependency>
     <groupId>taglibs</groupId>
     <artifactId>standard</artifactId>
     <version>1.1.2</version>
</dependency>-->
  <dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.11</version>
    <scope>test</scope>
  </dependency>
  
</dependencies>

Spring MVC binding List example – Required XML Configuration

Since JSTL tags are used in JSP so you need your view to resolve to JstlView, for that you need to add viewClass property in the bean definition for InternalResourceViewResolver in your DispatcherServlet configuration.

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  <property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
  <property name="prefix" value="/WEB-INF/jsp/" />
  <property name="suffix" value=".jsp" />
</bean>

Spring MVC binding List example – Model classes

List stores objects of the User class which is defined as given below.

public class User {

 private String firstName;
 private String lastName;
 private String email;
 public User() {}
 public User(String firstName, String lastName, String email) {
  this.firstName = firstName;
  this.lastName = lastName;
  this.email = email;
 }
 
 public String getFirstName() {
  return firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 public String getLastName() {
  return lastName;
 }
 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
}

Following class acts a container for the List of User objects.

public class UserListContainer {
  private List<User> users;

  public List<User> getUsers() {
    return users;
  }

  public void setUsers(List<User> users) {
    this.users = users;
  }
}

Spring MVC binding List example – Controller class

@Controller
public class UserController {
  @RequestMapping(value = "/getUsers", method = RequestMethod.GET)
  public String getUsers(Model model) throws Exception{
    List<User> users = getListOfUsers();
    UserListContainer userList = new UserListContainer();
    userList.setUsers(users);
    model.addAttribute("Users", userList);
    return "showUsers";
  }
    
  // Dummy method for adding List of Users
  private List<User> getListOfUsers() {
    List<User> users = new ArrayList<User>();
    users.add(new User("Jack", "Reacher", "abc@xyz.com"));
    users.add(new User("Remington", "Steele", "rs@cbd.com"));
    users.add(new User("Jonathan", "Raven", "jr@sn.com"));
    return users;
  }    
}

In the controller class there is a handler method getUsers() where a list of users is created and set to the UserListContainer which in turn is added as an attribute to the Model. Logical view name returned from the method is showUsers which resolves to a JSP at the location WEB-INF\jsp\showUsers.jsp.

Spring MVC binding List example – Views

If you just want to iterate the list and show the object fields then you can use the given JSP.

WEB-INF\jsp\showUsers.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring MVC List of objects display</title>
</head>
<body>
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
<c:forEach items="${Users.users}" var="user" varStatus="tagStatus">
  <tr>
    <td>${user.firstName}</td>
    <td>${user.lastName}</td>
    <td>${user.email}</td>
  </tr>
</c:forEach>
</table>
</body>
</html>

Here JSTL Core <c:forEach> tag is used to iterate over a collection of objects. Using var attribute you can provide a variable to point to the current item in the collection, which is "user" in the code.

Just showing the object fields

Binding list of objects

If you want to iterate the list, show the object fields and want to bind the List of objects again to modelAttribute then you can use the following JSP. The JSP displays a form with input boxes mapping to each object property. Form gives the functionality to update email of the user.

WEB-INF\jsp\updateUsers.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring MVC List of objects display</title>
</head>
<body>
<form:form method="POST" action="saveUsers" modelAttribute="Users">
<table>
<tr>
<th>First Name</th>
<th>Last Name</th>
<th>Email</th>
</tr>
<c:forEach items="${Users.users}" var="user" varStatus="tagStatus">
    <tr>
        <td><form:input path="users[${tagStatus.index}].firstName" value="${user.firstName}" readonly="true" /></td>
        <td><form:input path="users[${tagStatus.index}].lastName" value="${user.lastName}" readonly="true" /></td>
        <td><form:input path="users[${tagStatus.index}].email" value="${user.email}" /></td>
    </tr>
</c:forEach>
</table>
<input type="submit" value="Save" />
</form:form>
</body>
</html>

Important points to note here

  1. In this JSP Spring form tags are used for Spring MVC form fields and for looping the List JSTL tag is used. For these tag libraries following lines are added in the JSP.
    <%@taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%>
    <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
    
  2. Using varStatus attribute you can get the current index (loop status). Index is 0 based.
  3. Path attribute in form tag is the path to property for data binding. For example, in the first iteration of the loop, because of providing this path attribute, input element will translate to.
      
    <tr>
      <td><input id="users0.firstName" name="users[0].firstName" value="Jack" readonly="readonly" type="text" /></td>
      <td><input id="users0.lastName" name="users[0].lastName" value="Reacher" readonly="readonly" type="text" /></td>
      <td><input id="users0.email" name="users[0].email" value="abc@xyz.com" type="text" /></td>
    </tr>
    
    As you can see what is displayed in the input boxes maps to properties of the first User object in the List.

You need to change the UserController class to test this.

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.netjstech.springweb.model.User;
import com.netjstech.springweb.model.UserListContainer;

@Controller
public class UserController {
  @RequestMapping(value = "/getUsers", method = RequestMethod.GET)
  public String getUsers(Model model) throws Exception{
    List<User> users = getListOfUsers();
    UserListContainer userList = new UserListContainer();
    userList.setUsers(users);
    model.addAttribute("Users", userList);
    return "updateUsers";
  }
    
  // Dummy method for adding List of Users
  private List<User> getListOfUsers() {
    List<User> users = new ArrayList<User>();
    users.add(new User("Jack", "Reacher", "abc@xyz.com"));
    users.add(new User("Remington", "Steele", "rs@cbd.com"));
    users.add(new User("Jonathan", "Raven", "jr@sn.com"));
    return users;
  } 
  
  @RequestMapping(value = "/saveUsers", method = RequestMethod.POST)
  public String saveUsers(@ModelAttribute("Users") UserListContainer userList) throws Exception{
    List<User> users = userList.getUsers();
    for(User user : users) {
      System.out.println("Email- " + user.getEmail());
    }
    return "updateUsers";
  }
}

Once the application is deployed it can be accessed using the URL - http://localhost:8080/spring-mvc/getUsers which now resolves to updatedUsers.jsp view.

Showing the object fields and binding to Model

Binding list of objects Spring MVC

From the above image you can notice that email for two of the users is updated. On clicking save you can check in the console also to verify that the user object properties are actually updating.

Email- jack@xyz.com
Email- remingtons@cbd.com
Email- jr@sn.com
  

That's all for this topic Spring MVC - Binding List of Objects Example. If you have any doubt or any suggestions to make please drop a comment. Thanks!

>>>Return to Spring Tutorial Page


Related Topics

  1. Spring MVC File Download Example
  2. Spring MVC Exception Handling Example Using @ExceptionHandler And @ControllerAdvice
  3. Difference Between @Controller And @RestController Annotations in Spring
  4. Spring MVC Dot (.) Truncation Problem With @PathVariable Annotation
  5. Spring JdbcTemplate Insert, Update And Delete Example

You may also like-

  1. Spring Batch Processing With List of Objects in batchUpdate() Method
  2. registerShutdownHook() Method in Spring Framework
  3. ApplicationContextAware And BeanNameAware Interfaces in Spring Framework
  4. Autowiring Using Annotations in Spring
  5. Java Stream API Interview Questions And Answers
  6. Difference Between ArrayList And CopyOnWriteArrayList in Java
  7. Multiple Catch Blocks in Java Exception Handling
  8. Uber Mode in Hadoop