Sunday, March 1, 2020

Spring MVC Form Validation Example

In this post we’ll see a Spring MVC form validation example using Bean Validation API.

Technologies used

Following is the list of tools used for the Spring MVC form example with bean validation.

  1. Spring 5.0.8 Release (Spring core, spring web, spring webmvc).
  2. Java 10
  3. javax.validation API (2.1.0)
  4. hibernate-validator (6.0.12)
  5. Tomcat server V 9.0.10
  6. Eclipse Photon 4.8.0 for Java EE development (This Eclipse version supports Java 10)

Spring MVC Project structure using Maven

Maven Dependencies

Apart from Spring dependencies following dependencies are also to be added to the pom.xml for Spring bean validation.

<dependency>
    <groupId>javax.validation</groupId>
    <artifactId>validation-api</artifactId>
    <version>2.0.1.Final</version>
</dependency>
<dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>6.0.12.Final</version>
</dependency>

This should add the following jars-

validation-api-2.0.1.Final.jar
hibernate-validator-6.0.12.Final.jar
jboss-logging-3.3.2.Final.jar
classmate-1.3.4.jar

Why Bean Validation API and Hibernate Validator

Bean Validation API 2.x is based on the JSR 380 specification and HibernateValidator is the certified implementation of Bean Validation API. Using Hibernate Validator you can add application constraints in the form of annotations to your bean class.

Some of the annotations that are defined in Java Bean Validation API are as follows-

  • @NotBlank- The annotated element must not be null and must contain at least onenon-whitespace character.
  • @NotEmpty- The annotated element must not be null nor empty.
  • @NotNull- The annotated element must not be null.
  • @Size- The annotated element size must be between the specified boundaries. Boundaries can be specifies using main and max attributes.
  • @Digits- The annotated element must be a number within accepted range.
  • @Max- The annotated element must be a number whose value must be lower orequal to the specified maximum.
  • @Min- The annotated element must be a number whose value must be higher orequal to the specified minimum.
  • @Email- The string has to be a well-formed email address.

Spring MVC form example with validations step by step

In this Spring MVC user registration form example along with validation for fields the flow of the application is as given below.

  1. First is the home page (home.jsp) having a link to register a user.
  2. Clicking that link opens a form for registering a user (userRegister.jsp) where the fields are bound to the model bean User. We also need to validate the fields bound to the beans.
  3. On submitting the form the validation is done as per configuration and either the show user page (user.jsp) which just displays the entered field or the registration form with errors is displayed based on whether there are errors or not.

home.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://www.springframework.org/tags" prefix="s" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring MVC tutorial - Home JSP</title>
</head>
<body>
    <div>${message}</div>
    <a href='<s:url value="/registerUser"></s:url>'>Register User</a>
</body>
</html>

This is the landing page, as you can see Spring tags library is used here for creating the URL. For that you need to add the following line in your JSP.

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

The request for home page is handled by the following handler method in the Spring controller.

@RequestMapping(value = "/", method = RequestMethod.GET)
public String showHome(Model model) {  
 model.addAttribute("message", "Spring MVC Example - Form Processing");
 return "home";
}

The request path “/registerUser” is handled by the following handler method in the Spring controller.

@RequestMapping(value = "/registerUser", method = RequestMethod.GET)
public String registerUser(Model model) { 
 model.addAttribute(new User());
 return "userRegister";
}

As you can see in this handler method a new User instance is set into the model. It is required for binding a User instance to the Spring form. The logical view name returned by this method is “userRegister” which leads to the opening of registration form.

UserRegister.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>User Registration</title>
<style>
    .error { 
        color: green; font-weight: bold; 
    }
</style>
</head>
<body>
    <form:form action="showUser" modelAttribute="user" method="post">
    <table>
         <tr>
             <td>
                 <form:label path="firstName">First Name</form:label>
             </td>
             <td>
                 <form:input path="firstName" id="firstname" />
             </td>
              <td><form:errors path="firstName" cssClass="error"/></td>
         </tr>
         <tr>
             <td>
                 <form:label path="lastName">Last Name</form:label>
             </td>
             <td>
                 <form:input path="lastName" id="lastname" />
             </td>
             <td><form:errors path="lastName" cssClass="error"/></td>
         </tr>
         <tr>
             <td>
                 <form:label path="passWord">Password</form:label>           
             </td>
             <td>
                 <form:password path="passWord" id="password" />
             </td>
             <td><form:errors path="passWord" cssClass="error"/></td>
         </tr>
         <tr>
             <td>
                 <form:label path="email">Email</form:label>
             </td>
             <td>
                 <form:input path="email" id="email" />                 
             </td>
             <td><form:errors path="email" cssClass="error"/></td>
         </tr>
         <tr>
            <td>Subscribe to newsletter?:</td>
            <td><form:checkbox path="receiveNewsletter"/></td>
        </tr>
         <tr>
         <td><input type="submit" value="Submit"></td>
         </tr>
     </table>
    </form:form>
</body>
</html>

In this JSP (which is the user registration form), Spring form tags are used for Spring MVC form fields. The tag of interest here is “errors”. This tag renders field errors in an HTML 'span' tag. It provides access to the errors created in your controller or those that were created by any validators associated with your controller.

Also notice the attribute modelAttribute="user" in the form tag. This binds the form to the named variable. By default JSP assumes that the variable name of the form backing object is 'command' but it is a good practice to give your own name along with the modelAttribute.

The submission of this form is handled by the following handler method.

@RequestMapping(value = "/showUser", method = RequestMethod.POST)
public String showUser(@Valid @ModelAttribute("user") User user, BindingResult result, Model model) { 
 if(result.hasErrors()) {
  return "userRegister";
 }
 model.addAttribute("User", user);
 return "user";
}
If you notice the method parameter @Valid @ModelAttribute("user") User user, @ModelAttribute used here gives the same “user” instance as bound to Spring form. @Valid provides support for declarative validation of the bean annotated with @Valid annotation.

BindingResult stores the result of the Spring form validation and contains errors that may have occurred. That’s what is used for finding out if there are any errors in the Spring form validation, if there are errors then the same form is displayed again with errors. Relevant errors are displayed using the errors tag in the JSP. If there are no errors then the entered fields are displayed in the JSP page user.jsp.

user.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Spring MVC tutorial - User</title>
</head>
<body>
<table>
<tr>
<td>First Name: ${User.firstName}</td>
</tr>
<tr>
<td>Last Name: ${User.lastName}</td>
</tr>
<tr>
<td>Email: ${User.email}</td>
</tr>
<tr>
<td>Requires Newsletter: ${User.receiveNewsletter}</td>
</tr>
</table>
</body>
</html>

Spring bean validation using annotations

Till now we have seen the configuration and code required for Spring MVC form and bean validation code required for the view and controller. Not let’s shift focus to the Model.

Model bean (User.java)

import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

public class User {
 @NotNull
 @Size(min=5, max=15, message="{firstName.size}")
 private String firstName;
 @NotNull
 @Size(min=5, max=15, message="{lastName.size}")
 private String lastName;
 @NotNull
 @Size(min=8, max=20, message="{passWord.size}")
 private String passWord;
 @NotNull
 @Email(message="{email.msg}")
 private String email;
 
 private boolean receiveNewsletter;
    
 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 getPassWord() {
  return passWord;
 }
 public void setPassWord(String passWord) {
  this.passWord = passWord;
 }
 public String getEmail() {
  return email;
 }
 public void setEmail(String email) {
  this.email = email;
 }
 public boolean isReceiveNewsletter() {
  return receiveNewsletter;
 }
 public void setReceiveNewsletter(boolean receiveNewsletter) {
  this.receiveNewsletter = receiveNewsletter;
 }
}

This is the bean where Spring bean validation is configured for the form. Spring framework supports the Java Validation API in Spring MVC. Fields are annotated with the javax.validation.constraints annotation, for example firstName field is annotated with @NotNull which means this field can not be null and with @Size with max and min attribute for setting the minimum and maximum allowed characters. Using message attribute you can set the message which is referred from a properties file.

Properties file for validation messages

By default Spring framework looks for a file named ValidationMessages.properties, if you are using properties file with another name then some configuration is required. For this Spring form example we’ll name the properties files as “messages.properties” and see what all configuration is required to make it work.

messages.properties

firstName.size=First name is required and should be between {min} and {max} characters.
lastName.size=Last name is required and should be between {min} and {max} characters.
passWord.size=Password is required and should be between {min} and {max} characters.
email.msg=Please enter a valid email in the format abc@xyz.com.

Ensure that the key for each message is same as the placeholder you have given in the message attribute in your model bean.

Configuration for Spring bean validation

Following configuration is required in your Servlet’s XML file.

<mvc:annotation-driven validator="validator"/>

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="/WEB-INF/messages"/>
</bean>
<bean id="validator" class="org.springframework.validation.beanvalidation.LocalValidatorFactoryBean">
        <property name="validationMessageSource" ref="messageSource"/>
</bean> 

In the class ReloadableResourceBundleMessageSource you need to set path for your properties file as basename. Since I stored messages.properties file at the location /WEB-INF/messages.properties thus the value "/WEB-INF/messages".

Using LocalValidatorFactoryBean you can configure a default JSR-303 Validator as a Spring bean. Ensure that a JSR-303 provider, such as Hibernate Validator, is present in the classpath, that implementation will be detected automatically.

Also need to provide the bean name of the Validator that is to be used to validate Controller model objects using the validator attribute in <mvc:annotation-driven /> tag.

Spring MVC Form Example With Bean Validation - Controller class

We have already seen the relevant handler methods along with the JSPs, here is the full controller class used for the Spring form example with bean validation.

MessageController.java

import javax.validation.Valid;
import org.netjs.model.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class MessageController {
 @RequestMapping(value = "/", method = RequestMethod.GET)
 public String showHome(Model model) {  
  model.addAttribute("message", "Spring MVC Example - Form Processing");
  return "home";
 }
 
 @RequestMapping(value = "/registerUser", method = RequestMethod.GET)
 public String registerUser(Model model) { 
  model.addAttribute(new User());
  return "userRegister";
 }
 
 @RequestMapping(value = "/showUser", method = RequestMethod.POST)
 public String showUser(@Valid @ModelAttribute("user") User user, BindingResult result, Model model) { 
  if(result.hasErrors()) {
   return "userRegister";
  }
  model.addAttribute("User", user);
  return "user";
 }
}

Home page

Registration form errors

Registration form success

That's all for this topic Spring MVC Form Validation 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 Web MVC Tutorial
  2. Spring MVC Example With @RequestParam Annotation
  3. Spring MVC Exception Handling Example Using @ExceptionHandler And @ControllerAdvice
  4. Spring MVC File Upload (Multipart Request) Example
  5. How to Read Properties File in Spring Framework

You may also like-

  1. Using Spring Profiles to Switch Environment
  2. Run Time Injection Using Spring Expression Language(SpEL)
  3. Difference Between component-scan And annotation-config in Spring
  4. Different Bean Scopes in Spring
  5. ConcurrentHashMap in Java
  6. Race Condition in Java Multi-Threading
  7. Type Casting in Java
  8. How to Create Password Protected Zip File in Java