Spring MVC Tutorial

Core Spring MVC

Spring MVC - Annotation

Spring MVC - Form Handling

Spring MVC with JSTL

Spring MVC with REST API

Spring MVC with Database

Spring MVC - Validation

Validation is an essential part of any web application. Spring MVC provides built-in validation mechanisms that allow server-side validation of form data. Here's how you can implement validation in a Spring MVC application:

1. Maven Dependencies

To start, make sure you have the Spring Web MVC and Hibernate Validator dependencies:

<!-- Spring Web MVC -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.x.x.RELEASE</version>
</dependency>

<!-- Hibernate Validator -->
<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>6.x.x.Final</version>
</dependency>

2. Model with Validation Annotations

Consider a User model class. We'll add validation annotations to its fields:

import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Size;

public class User {

    @NotEmpty(message = "Username is required.")
    private String username;

    @Size(min = 6, message = "Password must be at least 6 characters.")
    private String password;

    // getters and setters
}

3. Controller

In your controller, annotate the model attribute parameter with @Valid to enable validation. Errors are captured in the BindingResult object:

@Controller
@RequestMapping("/user")
public class UserController {

    @GetMapping("/register")
    public String showRegistrationForm(Model model) {
        model.addAttribute("user", new User());
        return "registrationForm";
    }

    @PostMapping("/register")
    public String processRegistration(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return "registrationForm";
        }
        // Save user or further processing
        return "registrationSuccess";
    }
}

4. View

In your JSP view (registrationForm.jsp), display validation errors:

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

<form:form modelAttribute="user" method="POST">
    <form:errors path="*" cssClass="error" />
    
    <label for="username">Username:</label>
    <form:input path="username" />
    <form:errors path="username" cssClass="error" />
    
    <label for="password">Password:</label>
    <form:password path="password" />
    <form:errors path="password" cssClass="error" />

    <input type="submit" value="Register" />
</form:form>

5. Message Source (optional)

To externalize error messages or use more descriptive messages, you can configure a MessageSource:

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

Then, create a messages.properties file in the src/main/resources directory:

NotEmpty.user.username = Username cannot be blank!
Size.user.password = Password should have at least 6 characters.

This way, you can modify error messages without altering the Java code.

6. Handling Global Validation Errors

Sometimes, you might want to handle more complex validation logic beyond the field-level. In such cases, you can implement the Validator interface and override its methods.

Conclusion

Spring MVC, coupled with Hibernate Validator, makes it simple to handle form validation. It provides annotations for common validation scenarios and extensibility to handle custom validation logic when required.

  1. Spring MVC Validation Example:

    • Description: This is a basic example showcasing form validation in Spring MVC.

    • Code Snippet: (Model)

      public class User {
      
          @NotEmpty
          private String username;
      
          @Email
          private String email;
      
          // Getter and Setter
      }
      

      (Controller)

      @Controller
      public class UserController {
      
          @PostMapping("/register")
          public String registerUser(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {
              if (bindingResult.hasErrors()) {
                  return "registrationForm";
              }
              // Process user registration logic
              return "registrationSuccess";
          }
      }
      

      (Thymeleaf - registrationForm.html)

      <form th:object="${user}" th:action="@{/register}" method="post">
          <label for="username">Username:</label>
          <input type="text" id="username" name="username" th:field="*{username}" required />
          <span th:if="${#fields.hasErrors('username')}" th:errors="*{username}"></span>
      
          <label for="email">Email:</label>
          <input type="text" id="email" name="email" th:field="*{email}" required />
          <span th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></span>
      
          <button type="submit">Register</button>
      </form>
      
  2. Custom Validation in Spring MVC:

    • Description: This example demonstrates how to implement custom validation logic in Spring MVC.

    • Code Snippet: (Custom Validator)

      public class CustomValidator implements Validator {
      
          @Override
          public boolean supports(Class<?> clazz) {
              return User.class.equals(clazz);
          }
      
          @Override
          public void validate(Object target, Errors errors) {
              ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "field.required");
              // Custom validation logic
          }
      }
      

      (Controller)

      @Controller
      public class UserController {
      
          @Autowired
          private CustomValidator customValidator;
      
          @InitBinder
          protected void initBinder(WebDataBinder binder) {
              binder.setValidator(customValidator);
          }
      
          @PostMapping("/register")
          public String registerUser(@Valid @ModelAttribute("user") User user, BindingResult bindingResult) {
              if (bindingResult.hasErrors()) {
                  return "registrationForm";
              }
              // Process user registration logic
              return "registrationSuccess";
          }
      }