Engineering
Releases
News and Events

Integrating Spring MVC with jQuery for validation rules

I was thrilled to see in a recent survey from zeroturnaround that Spring MVC was voted the most popular web framework for Java.

This framework is very flexible and there are dozens of ways to use it. As with all flexible frameworks that have many options, it is important to discuss common practices.

The project I have created for this blog entry uses features common in many Spring MVC applications. You will find something like this:

In controllers you will find typical Spring MVC features for mapping requests, extracting request data through annotations, data binding, file upload…

On the other hand, inside JSPs, most of the HTML is written natively (as opposed to being generated by Spring MVC tags). Moreover, the Spring MVC tag libraries do not generate any Javascript code.

We are first going to discuss how to integrate Spring MVC with jQuery and Bean Validation. We will then see how to make those JSPs less verbose.

Bean Validation?

JSR 303 Bean Validation provides a comprehensive way to declare validation rules. Here is an example:

public class DiningForm {
  @Pattern(regexp="\\d{16}")

  private String creditCardNumber;

  @Size(1)
  private String merchantNumber;

  @Min(0)
  private double monetaryAmount;

  @NotNull
  private Date date;

  ...

}

When validation is called, an instance of DiningForm is validated against the annotations above.

From Spring 3.0, Spring MVC integrates with Bean validation for validation rules (that’s not the only way to do validation with Spring @MVC but it is obviously becoming the most common approach).

In a controller method, we can use @Valid as follows:

@RequestMapping(value="/update", method=RequestMethod.POST)
  public String update(@Valid DiningForm diningForm, BindingResult result) {

    if (result.hasErrors()) {
      return rewards/edit;
    }

    // continue on success...

  }
}

At the JSP level, error messages can be displayed using <form:errors />:

<form:form modelAttribute="diningForm">
  <form:input path="firstName"/>
  <form:errors path="firstName"/></form:form>

The code above is fairly simple and works well. But it does not generate any Javascript. Consequently it does not allow partial rendering or client side validation. Let’s see how to improve that!

Adding Javascript for partial rendering

Let us consider what happens when “first name” is empty.

In the previous example, the whole page was refreshed every time the form was submitted. Here is an extract of the HTML response:

Our target is to minimize the response size. We should be able to have such response instead (using json syntax):

{"status":"FAIL","result":[{"fieldName":"firstName","message":"firstName  may not be empty"}]}

Firstly, we will use a jQuery form submission to validate the form. When the form will be considered as valid, form submission will be triggered using regular HTML form submission (in that way we'll be able to redirect to a different page).

Let us first create a simple ValidationResponse class as follows:

public class ValidationResponse {
 private String status;
 private List errorMessageList;

 public String getStatus() {
   return status;
 }
 public void setStatus(String status) {
   this.status = status;
 }
 public List getErrorMessageList() {
   return this.errorMessageList;
 }
 public void setErrorMessageList(List errorMessageList) {
   this.errorMessageList = errorMessageList;
 }
}

Inside the controller class, we can add an action method:

@RequestMapping(value="/user.json")
public @ResponseBody ValidationResponse processForm (Model model, @Valid User user, BindingResult result ) {
 ValidationResponse res = new ValidationResponse();
 if(!result.hasErrors()){
   res.setStatus("SUCCESS");
 }
 // …
 return res;
}

Thanks to the @ResponseBody annotation, the returned object will be converted into JSON as explained in the diagram below:

Inside the JSP, the error message is parsed and displayed if appropriate. You can browse the Javascript code for more details.

According to progressive enhancement best practices, all Javascript code has been placed outside the HTML form. In case Javascript is disabled on a client’s browser, the form falls back into full page refresh.

Now that we have partial refresh working for validation rules, there are 2 points that still need improvement:

  • This page does not look cool!
  • This hello-world-style page has 100 lines already. There should be some ways to make it shorter.

Let’s make it pretty with Bootstrap

Even though this is not directly related to Spring MVC, it was hard for me to present a sample application with such a poor UI design. In case you haven’t heard of it yet, twitter Bootstrap is becoming the de facto CSS framework.  Many developers love it because it allows to make an acceptable design for a website with little effort. After copying the Bootstrap CSS and images, I just need to use the Boostrap CSS classes (see the JSP source code for more details). My form now looks like this:

Using custom tags to avoid the “JSP soup” syndrome

That’s where things become really interesting: even though we have some code which is working already, it is pretty hard to read. We are mixing together HTML, Javascript, CSS and JSP Expression Language. It would be more readable if my JSP code looked something like this:


<html:form modelAttribute="user"  id="add-user-form" formUrl="/userAjaxCustomTag.htm">
 <html:inputField name="firstName" label="Enter your first name:" />
 <html:inputField name="lastName" label="Enter your last name:" />
 <div>
   <button type="submit">Save changes</button>
   <button type="reset">Cancel</button>
 </div>
</html:form>

Custom tags are part of Java EE and also work great on Apache Tomcat. It is surprisingly easy to create a custom tag. Let us take a simple example with form input fields. We currently use this syntax (8 lines):

<div id="firstName">
 <label>Enter your first name:</label>
 <div>
   <form:input path="firstName" />
   <span>
     <form:errors path="firstName" />
   </span>
 </div>
</div>

Our goal is to use this instead (1 line):

<html:inputField name="firstName" label="Enter your first name:" />

In the WEB-INF folder, I can create a new tag file as follows:

Its content is the following:

<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<%@ attribute name="name" required="true" rtexprvalue="true" %>
<%@ attribute name="label" required="true" rtexprvalue="true" %>
<div id="${name}">
 <label>${label}</label>
<div>
  <form:input path="${name}"/>
  <span><form:errors path="${name}"/></span>
</div>

Back in userForm.jsp, I just need to declare the tag folder:

<%@ taglib prefix="html" tagdir="/WEB-INF/tags/html" %>

And I can use this newly created tag as follows:

<html:inputField name="firstName" label="Enter your first name:" />

Custom tags are well integrated in Eclipse/STS and I even have access to code completion:

In a similar fashion, I can also externalize the JavaScript code into a tag so I just have one line to call:

<ajax:formPartialRefresh validateUrl="/userAjaxBootstrap.json" formName="add-user-form"/>

Conclusion

We have discussed partial rendering in form validation with Spring MVC. In just a few minutes, we have turned JSP soup into something which is much simpler and easier to understand.

You are welcome to have a look at the corresponding sample application on github.

Credits: I would like to thank my friend Nicholas Ding who worked with me on building the code samples for this blog entry.

comments powered by Disqus