Spring 4 MVC - Form validation example using Hibernate Validator

Spring 4 MVC - Form validation example using Hibernate Validator

Technologies used:   Java SE 1.8 | Spring 4.3.7.RELEASE | Hibernate Validator 5.4.1.Final | Maven 3.3.9 | Apache Tomcat 7.0.47 | Eclipse Neon.3

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.

In our previous post, we have used the Spring’s Validator interface to validate a form. In this post, I will show you how to validate a form using the Hibernate validator framework.

 

Project structure

Review the following web project structure build using Maven.

Spring 4 MVC - Form validation example | BORAJI.COM

Refer this article to learn - How to create a web project using maven build tool in eclipse IDE.

 

Jar dependencies

In pom.xml file of your maven project, add the dependencies below.

<dependencies>
   <!-- Spring MVC Dependency -->
   <dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-webmvc</artifactId>
     <version>4.3.7.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>

 

Model class

Create a 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.

User.java

package com.boraji.tutorial.spring.model;

import java.util.List;

import javax.validation.constraints.Size;

import org.hibernate.validator.constraints.Email;
import org.hibernate.validator.constraints.NotEmpty;

public class User {

   @Size(max = 20, min = 3, message = "{user.name.empty}")
   private String name;

   @Email(message = "{user.email.invalid}")
   private String email;

   @NotEmpty(message = "{user.gender.empty}")
   private String gender;

   @NotEmpty(message = "{user.languages.empty}")
   private List<String> languages;

   // Getter and Setter method

}

By default, Hibernate Validator provides the validation messages in ValidationMessages.properties resource bundle for each constraint. But you can override the default messages by providing a custom resource bundle in the class path.

To override the default error messages, create a messages.properties file under src/main/resources folder.

messages.properties

user.name.empty = Name entered is invalid. It must be between {2} and {1} characters.
user.email.invalid = Invalid email! Please enter valid email.
user.gender.empty = Select gender.
user.languages.empty = Select at least one language.

In Spring web configuration, use LocalValidatorFactoryBean.setValidationMessageSource() method to set the custom resource bundle for validation messages.

 

Controller class

To validate the user input form, just annotated the model attribute of a handler method  with the @Valid annotation as follows.

UserController.java

package com.boraji.tutorial.spring.controller;

import java.util.Locale;

import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PostMapping;

import com.boraji.tutorial.spring.model.User;

/**
 * @author imssbora
 */
@Controller
public class UserController {

   @GetMapping("/")
   public String userForm(Locale locale,Model model) {
      model.addAttribute("user", new User());
      return "userForm";
   }

   @PostMapping("/saveUser")
   public String saveUser(@ModelAttribute("user") @Valid User user, BindingResult result,
         Model model) {

      if (result.hasErrors()) {
         return "userForm";
      }
      return "success";
   }
}

 

JSP Views

Create userForm.jsp file under src\main\webapp\WEB-INF\views folder to take user input.

userForm.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
<[email protected] uri="http://www.springframework.org/tags/form" prefix="form"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>BORAJI.COM</title>
<style type="text/css">
.error {
	color: red;
}
</style>
</head>
<body>
  <h2>User Input From</h2>
  <hr />
  <form:form action="saveUser" method="post" modelAttribute="user">
    <table>
      <tr>
        <th>Name</th>
        <td>
          <form:input path="name" /> 
          <form:errors path="name" cssClass="error" />
         </td>
      </tr>
      <tr>
        <th>Email</th>
        <td>
            <form:input path="email" /> 
            <form:errors path="email" cssClass="error" />
         </td>
      </tr>
      <tr>
        <th>Gender</th>
        <td>
          <form:radiobutton path="gender" value="Male" label="Male" /> 
          <form:radiobutton path="gender" value="Female" label="Female" /> 
          <form:errors path="gender" cssClass="error" />
         </td>
      </tr>
      <tr>
        <th valign="top">Languages</th>
        <td>
          <form:select path="languages" multiple="true">
            <form:option value="US English">US English</form:option>
            <form:option value="UK English">UK English</form:option>
            <form:option value="Spanish">Spanish</form:option>
            <form:option value="Hindi">Hindi</form:option>
            <form:option value="Mandarin">Mandarin</form:option>
          </form:select>
          <form:errors path="languages" cssClass="error" />
         </td>
      </tr>
      <tr>
        <td><button type="submit">Submit</button></td>
      </tr>
    </table>
  </form:form>
</body>
</html>

The <form:errors> is used to display the error messages and the path attribute indicate the field name of model class for which the error message should be displayed.

Create another success.jsp file under src\main\webapp\WEB-INF\views folder to display the user information on successful validation.

success.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
  pageEncoding="ISO-8859-1"%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>BORAJI.COM</title>
</head>
<body>
  <h2>User Success From</h2>
  <hr />

  <table>
    <tr>
      <th>Name</th>
      <td>${user.name}</td>
    </tr>
    <tr>
      <th>Email</th>
      <td>${user.email}</td>
    </tr>
    <tr>
      <th>Gender</th>
      <td>${user.gender}</td>
    </tr>
    <tr>
      <th valign="top">Languages</th>
      <td>${user.languages}</td>
    </tr>
  </table>
</body>
</html>

 

Spring configuration

Create a web @Configuration class annotated with @EnableWebMvc and @ComponentScan as follows.

Also declare a Validator bean method to set the custom resource bundles (i.e. messages.properties) for validation messages.

WebConfig.java

package com.boraji.tutorial.spring.config;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.validation.Validator;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
import org.springframework.web.servlet.view.JstlView;

/**
 * @author imssbora
 */

@Configuration
@EnableWebMvc
@ComponentScan(basePackages = { "com.boraji.tutorial.spring.controller",
      "com.boraji.tutorial.spring.validator" })
public class WebConfig extends WebMvcConfigurerAdapter {

   @Bean
   public InternalResourceViewResolver resolver() {
      InternalResourceViewResolver resolver = new InternalResourceViewResolver();
      resolver.setViewClass(JstlView.class);
      resolver.setPrefix("/WEB-INF/views/");
      resolver.setSuffix(".jsp");
      return resolver;
   }

   @Bean
   public MessageSource messageSource() {
      ResourceBundleMessageSource source = new ResourceBundleMessageSource();
      source.setBasename("messages");
      return source;
   }

   @Override
   public Validator getValidator() {
      LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
      validator.setValidationMessageSource(messageSource());
      return validator;
   }

}

 

Servlet container initialization

Create a container initializer class by extending the AbstractAnnotationConfigDispatcherServletInitializer class as follows.

MyWebAppInitializer.java

package com.boraji.tutorial.spring.config;

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

/**
 * @author imssbora
 */
public class MyWebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] {};
   }

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

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}

 

Build + Deploy + Run application

Use the following maven commands to build, deploy and run embedded Tomcat server.

mvn clean install  (This command triggers war packaging)

mvn tomcat7:run (This command run embedded tomcat and deploy war file automatically)

You can refer this link to learn how to run the above commands in Eclipse IDE.


Type the following URLs in browser's address bar to open the user input from.

http://localhost:8080/

Spring 4 MVC - Form validation example | BORAJI.COM

On validation failure, user input form will be displayed with error messages.

Spring 4 MVC - Form validation example | BORAJI.COM

On validation success, a new page will be displayed with user details as below.

Spring 4 MVC - Form validation example | BORAJI.COM