Getting Started with Forms in Spring MVC

1. Overview

In this article, we will discuss Spring forms and data binding to a controller. Also, we will have a look at one of the main annotations in Spring MVC i.e. @ModelAttribute.

Of course, Spring MVC is a complex topic with lots of things you need to understand to use it to its full potential, so definitely dig deeper into the framework here.

2. The Model

First – let’s define a simple entity that we’re going to display and bind to the form:

public class Employee {
    private String name;
    private long id;
    private String contactNumber;

    // standard getters and setters
}

This will be our form-backing object.

3. The View

Next – let’s define the actual form, and of course, the HTML file that contains it. We’re going to be using a page where a new employee is created/registered:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<html>
    <head>
    </head>
    <body>
        <h3>Welcome, Enter The Employee Details</h3>
        <form:form method="POST" 
          action="/spring-mvc-xml/addEmployee" modelAttribute="employee">
             <table>
                <tr>
                    <td><form:label path="name">Name</form:label></td>
                    <td><form:input path="name"/></td>
                </tr>
                <tr>
                    <td><form:label path="id">Id</form:label></td>
                    <td><form:input path="id"/></td>
                </tr>
                <tr>
                    <td><form:label path="contactNumber">
                      Contact Number</form:label></td>
                    <td><form:input path="contactNumber"/></td>
                </tr>
                <tr>
                    <td><input type="submit" value="Submit"/></td>
                </tr>
            </table>
        </form:form>
    </body>
</html>

First – notice that we’re including a tag library into our JSP page – the form taglib – to help with defining our form.

Next – the <form:form> tag plays an important role here; it’s very similar to the regular HTLM <form> tag but the modelAttribute attribute is the key which specifies a name of the model object that backs this form:

<form:form method="POST" 
  action="/SpringMVCFormExample/addEmployee" modelAttribute="employee">

This will correspond to the @ModelAttribute later on in the controller.

Next – each input fields is using yet another useful tag from the Spring Form taglib – form: prefix. Each of these fields specifies path attribute – this must correspond to a getter/setter of the model attribute (in this case, the Employee class). When the page is loaded, the input fields are populated by Spring, which calls the getter of each field bound to an input field. When the form is submitted, the setters are called to save the values of the form to the object.

Finally – when the form is submitted, the POST handler in the controller is invoked and the form is automatically bound to the employee argument that we passed in.

Basic Forms with Spring MVC

4. The Controller

Now, let’s look at the Controller that’s going to handle the back end:

@Controller
public class EmployeeController {

    @RequestMapping(value = "/employee", method = RequestMethod.GET)
    public ModelAndView showForm() {
        return new ModelAndView("employeeHome", "employee", new Employee());
    }

    @RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
    public String submit(@Valid @ModelAttribute("employee")Employee employee, 
      BindingResult result, ModelMap model) {
        if (result.hasErrors()) {
            return "error";
        }
        model.addAttribute("name", employee.getName());
        model.addAttribute("contactNumber", employee.getContactNumber());
        model.addAttribute("id", employee.getId());
        return "employeeView";
    }
}

The controller defines two simple operations – the GET for displaying data in the form, and the POST for the create operation, via form’s submit.

Also note that if the object called “employee” is not added to the model, Spring would complain when we try to access the JSP because the JSP will be set up to bind the form to the “employee” model attribute:

java.lang.IllegalStateException: 
  Neither BindingResult nor plain target object 
    for bean name 'employee' available as request attribute
  at o.s.w.s.s.BindStatus.<init>(BindStatus.java:141)

To access our form backing object, we need to inject it via the @ModelAttribute annotation.

An @ModelAttribute on a method argument indicates the argument will be retrieved from the model. If not present in the model, the argument will be instantiated first and then added to the model.

5. Handling Bind Errors

By default, Spring MVC throws an exception when errors occur during request binding. This usually not what we want, instead, we should be presenting these errors to the user. We’re going to use a BindingResult by adding one as an argument to our controller method:

public String submit(
  @Valid @ModelAttribute("employee") Employee employee,
  BindingResult result,
  ModelMap model)

The BindingResult argument needs to be positioned right after our form backing object – it’s one of the rare cases where the order of the method arguments matters. Otherwise, we’ll run into the following exception:

java.lang.IllegalStateException: 
  Errors/BindingResult argument declared without preceding model attribute. 
    Check your handler method signature!

Now – an exception is no longer thrown; instead, errors will be registered on the BindingResult that is passed to the submit method. At this point, we can handle these errors in a variety of ways – for example, the operation can be canceled:

@RequestMapping(value = "/addEmployee", method = RequestMethod.POST)
public String submit(@Valid @ModelAttribute("employee")Employee employee, 
  BindingResult result,  ModelMap model) {
    if (result.hasErrors()) {
        return "error";
    }
    
    //Do Something
    return "employeeView";
}

Notice how, in case the result contains errors, we’re returning another view to the user in order to display these errors correctly. Let’s take a look at that view – error.jsp:

<html>
    <head>
    </head>

    <body>
        <h3>Please enter the correct details</h3>
        <table>
            <tr>
                <td><a href="employee">Retry</a></td>
            </tr>
        </table>
    </body>

</html>

6. Displaying an Employee

Finally, besides creating a new employee, we can also simply display one – here’s the quick view code for that:

<body>
    <h2>Submitted Employee Information</h2>
    <table>
        <tr>
            <td>Name :</td>
            <td>${name}</td>
        </tr>
        <tr>
            <td>ID :</td>
            <td>${id}</td>
        </tr>
        <tr>
            <td>Contact Number :</td>
            <td>${contactNumber}</td>
        </tr>
    </table>
</body>

The JSP page is simply using EL expressions to display values of properties of the Employee object in the model.

7. Testing the Application

The simple application can be deployed – for example in a Tomcat server – and accessed locally:

http://localhost:8080/spring-mvc-xml/employee

This is the view containing the main form – before the submit operation:

Spring MVC Form example – Submit

After the submit, the data is displayed:

Spring MVC Form example – View

And that’s it – a working example of a simple form with Spring MVC, with validation.

The implementation of this Spring MVC tutorial can be found in the GitHub project – this is a Maven-based project, so it should be easy to import and run as it is.

Finally, as I was saying right at the beginning of the article, you should definitely dig deeper into Spring MVC.

Related posts:

Xử lý ngoại lệ đối với trường hợp ghi đè phương thức trong java
Java Program to Find Maximum Element in an Array using Binary Search
ETags for REST with Spring
Java Program to Find the Median of two Sorted Arrays using Binary Search Approach
Get and Post Lists of Objects with RestTemplate
DistinctBy in the Java Stream API
Hướng dẫn Java Design Pattern – Prototype
Java Program to Implement Branch and Bound Method to Perform a Combinatorial Search
Java Program to Implement Circular Doubly Linked List
Spring Boot - Zuul Proxy Server and Routing
HttpClient Connection Management
Tìm hiểu cơ chế Lazy Evaluation của Stream trong Java 8
Send email with JavaMail
Java Program to Implement Heap Sort Using Library Functions
Array to String Conversions
Entity To DTO Conversion for a Spring REST API
HashSet trong Java hoạt động như thế nào?
Converting between an Array and a List in Java
Java 8 Collectors toMap
Java Program to Implement Hash Tables Chaining with Binary Trees
Xử lý ngoại lệ trong Java (Exception Handling)
CharSequence vs. String in Java
Spring Cloud – Securing Services
Java Program to Implement the Binary Counting Method to Generate Subsets of a Set
Ways to Iterate Over a List in Java
Java Program to Implement Stack using Linked List
Java Program to Implement Triply Linked List
Java Program to implement Circular Buffer
Java Program to Generate a Random UnDirected Graph for a Given Number of Edges
How to Manually Authenticate User with Spring Security
Examine the internal DNS cache
Java Program to Implement Caesar Cypher