In this tutorial, we're going to learn how to perform form validation in the Spring MVC web application using Java bean validation annotations.
Note that we don't use Spring boot, we use plain Spring MVC libraries in this tutorial.
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 Hibernate validator library which is the implementation of Java's standard Bean Validation API.
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.
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).
Follow below 10 development steps to develop a complete end-to-end Spring MVC form validation application.
Let's create a Maven-based web application either using a command line or from Eclipse IDE.
Once you created a maven web application, refer to the pom.xml file jar dependencies.
Refer to the following pom.xml file and add 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>
Standard project structure for your reference -
As the name suggests Spring MVC, look at the above diagram we are using the Model-View-Controller approach.
Model - Customer.java
Views - customer-form.jsp and customer-confirmation.jsp Controller - CustomerController.javaNext step, we will configure Spring beans using Java-based configuration.
Create an MVCConfig class and annotated it 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; @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 the above file.
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; 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.
Let's create a Customer model class, whose field names are annotated with Hibernate Validator constraint annotations. We will use this class for binding form 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.
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"; } } }
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>
As we are using the maven build tool so first, we will need to build this application using the 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
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 the customer confirmation success page as shown below: