Preserving Validation Error Messages on Spring MVC Form Post-Redirect-Get

Here is a simple Spring MVC guestbook form complete with validation error messages:

formvalidation

To code this, firstly add hibernate-validator to your classpath (pom.xml):

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-validator</artifactId>
  <version>4.3.1.Final</version>
</dependency>

And we’ll code the form as a java class. Notice we added few validators using annotations provided by hibernate-validators. The associated error message is also coded here :

public class MessageForm {
  @NotBlank(message = "Please provide your name")
  private String name;

  @NotBlank(message = "Please provide your email")
  @Email(message = "Invalid email address")
  private String email;

  @Size(min = 10, message = "Please enter at least 10 characters")
  private String message;

  // getters & setters..
}

Next we’ll create the JSP view containing html code for the form. Notice the usage of <form:errors> tag to display validation error messages

<form:form modelAttribute="messageForm" method="post">
  <ul>
    <li><form:label path="name">Name</form:label> : 
      <form:input type="text" path="name" />
      <form:errors path="name" cssClass="red" /></li>

    <li><form:label path="email">Email</form:label> : 
      <form:input type="text" path="email" />
      <form:errors path="email" cssClass="red" /></li>

    <li><form:label path="message">Message</form:label> :
      <form:textarea path="message" />
      <form:errors path="message" cssClass="red" /></li>
    <li><button>Send</button></li>
  </ul>
</form:form>

On our controller class, the method that serves the guestbook form first checks if the model attribute “messageForm” exists before creating a new one. This is to cover the scenario where validation fails and user has to be redirected back :

@Controller
public class GuestbookController {

  /**
   * Serve guestbook form.
   */
  @RequestMapping(value = "/", method = RequestMethod.GET)
  public String home(Model model) {
    if(!model.containsAttribute("messageForm")) model.addAttribute("messageForm", new MessageForm());
    return "guestbook";
  }

  // more code ..
}

On the message submission handler, notice the usage of @Valid annotation. This will trigger validation declared using annotation on our form class above. Validation errors can be checked from the associated BindingResult object. Here if error occurs we redirect the user back to the form and display the error messages (pay attention to the “redirect:” prefix). Notice the BindingResult object is passed via RedirectAttributes using org.springframework.validation.BindingResult.messageForm name, this will ensure the messages can be accessed using <form:errors > tags.

...
  /**
   * Form post handler
   */
  @RequestMapping(value = "/", method = RequestMethod.POST)
  public String send(
      @Valid @ModelAttribute("messageForm") MessageForm messageForm, 
      BindingResult binding, 
      RedirectAttributes redirectAttributes) {
  
    // Redirect back into form page if errors detected
    if (binding.hasErrors()) {
      redirectAttributes.addFlashAttribute("org.springframework.validation.BindingResult.messageForm", binding);
      redirectAttributes.addFlashAttribute("messageForm", messageForm);
      return "redirect:/";
    }
  
    return "redirect:/result";
  }
...

And finally display a success message if no errors

...
  /**
   * Result page, simply displays 'message has ben sent'
   */
  @RequestMapping(value = "/result", method = RequestMethod.GET)
  public String result() {
    return "result";
  }
...

Get The Source Code

Source code for this blog is available to checkout via git:

git clone https://gerrytan@bitbucket.org/gerrytan/formvalidation1.git

To run it, simply use mvn clean tomcat:run, and point your browser to http://localhost:8080/formvalidation1

Thanks Oscar for describing the BindingResult preservation techniques on redirection.

Advertisements

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s