Spring MVC 5 Form Validation with Annotations Tutorial



In this quick tutorial, we're going to learn about Spring MVC form validation using annotations like @NotNull, @Size, @Min, @Max, @Email, @Pattern etc.
So, what's the need for validation? Well, you may have a form and you may want to validate the fields to make sure you have required fields, numbers in a given range, validate the format, for example, for a postal code or you may want to add your own custom business rule for validation etc.
In this tutorial, we will use Java's standard Bean validation API and it defines a meta-model and API for entity validation.
Before you get started, check out Spring Data JPA Tutorial and Spring MVC Tutorial

    Spring MVC Tutorials and Articles

Hibernate Validator framework is the reference implementation of JSR 303 for java bean validation. JSR 303 defines a metadata model and API for entity and method validation.
Now, let's talk about Spring support for validation. So, Spring version 4 and higher supports the Bean Validation API which is a good thing. So, it's actually the preferred method for validation when building Spring apps.
We will use below important Hibernate Validator constraint annotations in this example.
  1. @NotNull
  2. @Size
  3. @Min
  4. @Max
  5. @Email
  6. @Pattern
  7. @NotEmpty
These all are built-in validation rules but we can also create our own custom validation rule along with our own custom Java annotation.
In this example, we will use a Java-based configuration that is we configure the Spring Dispatcher Servlet and spring beans configuration using all Java Code (no XML).

Tools and technologies used

  • Spring MVC - 5.1.0 RELEASE
  • JDK - 1.8 or later
  • Maven - 3.5.1
  • Apache Tomcat - 8.5
  • IDE - STS/Eclipse Neon.3
  • JSTL - 1.2.1
  • JSP - 2.3.1
Follow below 10 development steps to develop complete end-to-end Spring MVC form validation application.

Development Steps

  1. Create Maven Web Application
  2. Add Dependencies - pom.xml File
  3. Project Structure
  4. Spring Configuration - MVCConfig.java
  5. Servlet Container Initialization - SpringMvcDispatcherServletInitializer.java
  6. Model Class - Customer.java
  7. Controller Class - CustomerController.java
  8. Views - customer-form.jsp and customer-confirmation.jsp
  9. Build and Run an application
  10. Demo

1. Create Maven Web Application

Let's create a Maven based web application either using a command line or from Eclipse IDE.
1.  Use Guide to Create Maven Web Application link to create a maven project using a command line. 
2. Use Create Maven Web Application using Eclipse IDE link to create maven web application using IDE Eclipse.
Once you created maven web application, refer below pom.xml file jar dependencies.

2. Add Dependencies - pom.xml File

Refer the following pom.xml file and add jar dependencies to your pom.xml.
<project
    xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>net.javaguides.springmvc</groupId>
    <artifactId>springmvc5-form-validation</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>springmvc5-form-validation Maven Webapp</name>
    <url>http://maven.apache.org</url>
    <properties>
        <failOnMissingWebXml>false</failOnMissingWebXml>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.1.0.RELEASE</version>
        </dependency>
        <!-- Hibernate Validator -->
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-validator</artifactId>
            <version>5.4.1.Final</version>
        </dependency>
        <!-- JSTL Dependency -->
        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>javax.servlet.jsp.jstl-api</artifactId>
            <version>1.2.1</version>
        </dependency>
        <dependency>
            <groupId>taglibs</groupId>
            <artifactId>standard</artifactId>
            <version>1.1.2</version>
        </dependency>
        <!-- Servlet Dependency -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <!-- JSP Dependency -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>javax.servlet.jsp-api</artifactId>
            <version>2.3.1</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <sourceDirectory>src/main/java</sourceDirectory>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.5.1</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

3. Project Structure

Standard project structure for your reference -
As the name suggests Spring MVC, look at the above diagram we are using Model-View-Controller approach.
Model - Customer.java
Views - customer-form.jsp and customer-confirmation.jsp 
Controller - CustomerController.java 
Next step, we will configure Spring beans using Java-based configuration.

4. Spring Configuration - MVCConfig.java

Create an MVCConfig class and annotated with @Configuration, @EnableWebMvc, and @ComponentScan annotations.
package net.javaguides.springmvc.form.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * @author Ramesh Fadatare
 */

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = {
    "net.javaguides.springmvc.form"
})
public class MVCConfig implements WebMvcConfigurer {

    @Bean
    public InternalResourceViewResolver resolver() {
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        resolver.setViewClass(JstlView.class);
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");
        return resolver;
    }
}
Let's look at few important annotations from above file.
  • The @Configuration is a class-level annotation indicating that an object is a source of bean definitions.
  • The @EnableWebMvc enables default Spring MVC configuration and provides the functionality equivalent to mvc:annotation-driven/ element in XML based configuration.
  • The @ComponentScan scans the stereotype annotations (@Controller, @Service etc...) in a package specified by basePackages attribute.

5. Servlet Container Initialization - SpringMvcDispatcherServletInitializer.java

In Spring MVC, The DispatcherServlet needs to be declared and mapped for processing all requests either using java or web.xml configuration.
In a Servlet 3.0+ environment, you can use AbstractAnnotationConfigDispatcherServletInitializer class to register and initialize the DispatcherServlet programmatically as follows.
package net.javaguides.springmvc.form.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

/**
 * @author Ramesh Fadatare
 */
public class SpringMvcDispatcherServletInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

    @Override
    protected Class << ? > [] getRootConfigClasses() {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    protected Class << ? > [] getServletConfigClasses() {
        return new Class[] {
            MVCConfig.class
        };
    }

    @Override
    protected String[] getServletMappings() {
        return new String[] {
            "/"
        };
    }
}
Next step, we will create a Customer class Model.

6. Model Class - Customer.java

Let's create a Customer model class, whose field names are annotated with Hibernate Validator constraint annotations.
We will use this class for binding from data to the model and exposing model data to views.
package net.javaguides.springmvc.form.model;

import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;

public class Customer {

    private String firstName;

    @NotNull(message = "is required")
    @Size(min = 1, message = "is required")
    private String lastName;

    @NotNull(message = "is required")
    @Min(value = 0, message = "must be greater than or equal to zero")
    @Max(value = 10, message = "must be less than or equal to 10")
    private Integer freePasses;

    @Pattern(regexp = "^[a-zA-Z0-9]{5}", message = "only 5 chars/digits")
    private String postalCode;

    @NotNull(message = "is required")
    @Email(message = "Invalid email! Please enter valid email")
    private String email;

    public String getPostalCode() {
        return postalCode;
    }

    public void setPostalCode(String postalCode) {
        this.postalCode = postalCode;
    }

    public Integer getFreePasses() {
        return freePasses;
    }

    public void setFreePasses(Integer freePasses) {
        this.freePasses = freePasses;
    }

    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;
    }
}
Note that we have use Validation annotations such as @NotNull, @Size, @Min, @Max, @Email,  @Pattern, and @NotEmpty.

7. Controller Class - CustomerController.java

Let's create CustomerController controller class annotated with @Controller annotation as follows:
package net.javaguides.springmvc.form.controller;

import javax.validation.Valid;

import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;

import net.javaguides.springmvc.form.model.Customer;

@Controller
@RequestMapping("/customer")
public class CustomerController {

    // add an initbinder ... to convert trim input strings
    // remove leading and trailing whitespace
    // resolve issue for our validation

    @InitBinder
    public void initBinder(WebDataBinder dataBinder) {

        StringTrimmerEditor stringTrimmerEditor = new StringTrimmerEditor(true);

        dataBinder.registerCustomEditor(String.class, stringTrimmerEditor);
    }


    @RequestMapping("/showForm")
    public String showForm(Model theModel) {

        theModel.addAttribute("customer", new Customer());

        return "customer-form";
    }

    @RequestMapping("/processForm")
    public String processForm(
        @Valid @ModelAttribute("customer") Customer theCustomer,
        BindingResult theBindingResult) {

        if (theBindingResult.hasErrors()) {
            return "customer-form";
        } else {
            return "customer-confirmation";
        }
    }
}

8. Views - customer-form.jsp and customer-confirmation.jsp

customer-form.jsp

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>

    <html>

    <head>
        <title>Customer Registration Form</title>

        <style>
            .error {
                color: red
            }
        </style>
    </head>

    <body>
        <h1> Spring MVC 5 - Form Validation Example</h1>
        <i>Fill out the form. Asterisk (*) means required.</i>
        <br><br>

        <form:form action="processForm" modelAttribute="customer">

            First name:
            <form:input path="firstName" />

            <br><br> Last name (*):
            <form:input path="lastName" />
            <form:errors path="lastName" cssClass="error" />

            <br><br> Free passes (*):
            <form:input path="freePasses" />
            <form:errors path="freePasses" cssClass="error" />

            <br><br> Email (*):
            <form:input path="email" />
            <form:errors path="email" cssClass="error" />

            <br><br> Postal Code:
            <form:input path="postalCode" />
            <form:errors path="postalCode" cssClass="error" />

            <br><br>

            <input type="submit" value="Submit" />

        </form:form>

    </body>

    </html>

customer-confirmation.jsp

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

    <!DOCTYPE html>

    <html>

    <head>
        <title>Customer Confirmation</title>
    </head>

    <body>

        The customer is confirmed: ${customer.firstName} ${customer.lastName}

        <br><br> Free passes: ${customer.freePasses}

        <br><br> Email: ${customer.email}

        <br><br> Postal Code: ${customer.postalCode}

    </body>

    </html>

9. Build and Run an application

As we are using maven build tool so first, we will need to build this application using following maven command:
clean install
Once build success, then we will run this application on tomcat server 8.5 in IDE or we can also deploy war file on external tomcat webapps folder and run the application.

10. Demo

Once an application is up and running in tomcat server then hit this link into browser: http://localhost:8080/springmvc5-form-validation/customer/processForm
On entering the URL, you will see the following page.
Fill the above form with proper input and hit submit button will navigate to customer confirmation success page as shown below:
That's all about using built-in validation rules. Next article we create our own custom validation rule along with our own custom Java annotation, really great stuff.

Comments