Skip to main content

Ajax Form Validation Using Spring and DWR

February 8, 2007

alt="{cs.r.title}" border="0" align="left" hspace="10" vspace="0">



Validating input is a critical element to almost any non-trivial
software application. Regardless of the purpose of the application,
its architecture, or the platform on which it will run, it is
standard practice to verify that all input is valid before being
accepted. In three-tier web applications, the choice must be made
to validate user input on either the server, the client, or both.
Server-side validation is the industry standard but it requires the
user to fill out the form, click Submit, and wait for a page
refresh. While the best technical solution, it provides a poor
but accepted user experience. Although client-side validation,
using JavaScript, provides immediate feedback and an enhanced user
experience, it has many disadvantages such as being tedious and
error-prone to develop, being hard to test, and leading to fragile
code. Inconsistent implementations across different browsers and
the fact that a user can disable JavaScript is enough to conclude
that client-side validation alone is not sufficient. Although a
hybrid approach of performing validation on both the client and
server may seem like a good solution on the surface it doesn't take
long to realize that the increased development time, duplication of
logic, and inevitable maintenance and testing problems quickly
outweigh the advantages.

An ideal solution would be to write your validation logic on the
server and then have some way of invoking it directly from the
client, giving the appearance of client-side validation. Should
some circumstance cause this seemingly client-side validation to
not be executed correctly, such as a browser incompatibility or
JavaScript being turned off, this mechanism should fail gracefully
and allow the traditional server-side validation processing to work
as usual. In effect, you would gain all the advantages of the hybrid
approach while avoiding its disadvantages and the disadvantages of
purely client-side validation.

With the rise and subsequent acceptance of Ajax, you can now do
exactly that. Using what is referred to as Ajax form
validation
, just after a user finishes filling out an input
form field a background process of the browser can transparently
transmit the form input value to the server. The server then
performs validation of the input values. Should the server determine
an input value is invalid, a validation error message is returned
to the browser and dynamically displayed next to the invalid form
input entry. While some advanced web applications have demonstrated
this functionality for a short while, the software has typically
been hardwired and custom-coded for each form or for each
application.

This article presents a generic and reusable Ajax form
validation design that, by using existing open source components
and leveraging your applications' existing validation logic, can
easily and quickly be used to Ajax validate every form of your web-based applications. To provide a concrete example, the registration
form of the
jPetstore sample application
, provided by the Spring framework,
has been modified. This article outlines the steps taken to modify
jPetstore and discusses the design- and implementation-level
details.

Before getting started, it should be noted that this article
makes use of the Spring
framework
and a small amount of Spring and Spring MVC
familiarity is assumed. Readers needing additional Spring
documentation should see the Resources section. If you are not
familiar with Spring, don't panic. Conceptually, all of the
information presented applies equally to any web-based MVC
framework and it would be trivial to modify the examples provided
to work with Struts or JSF, for example.

Getting Started

The following steps will guide you through getting the sample
code up and running:

  1. Download Spring and its dependencies from the Spring downloads
    page
    .
  2. Unzip the downloaded file to a convenient location. This
    directory will be referred to as SPRING_HOME.
  3. Download a modified jPetstore, which has been modified to
    include Ajax validation on the user registration page, from
    the link in the Resources section.
  4. Unzip the modified jPetstore into SPRING_HOME/samples,
    overwriting the original jpetstore directory.
  5. Build and deploy jPetstore to your application server.
  6. Start the HSQL database needed by jPetstore by going into
    SPRING_HOME/samples/jpetstore/db/hsqldb and double-clicking
    server.bat.
  7. Start your application server.
  8. Point your browser to
    http://localhost:8080/jpetstore/shop/newAccount.do.

With the sample application up and running, we can move along
and discuss the three components required to perform Ajax
validation: the server-side validation infrastructure and logic, an
Ajax communication framework to marshal information between the
server and client, and the client-side JavaScript used to control
the process. Because the use of a server-side validation mechanism
is probably the most familiar and because your current or planned
application would undoubtedly have some server-side validation,
we'll start there.

Server-Side Validation Using Spring

The first component needed to incorporate Ajax validation into
your web application is a server-side validation framework. Spring,
a full-stack Java/J2EE application framework that has gained
tremendous popularity, and its validation framework are
demonstrated through the jPetstore sample application. Although
Spring offers incredibly powerful functionality across the entire
spectrum of Java software development, two of Spring's greatest
strengths are its simplicity and straightforward design. Input
validation is an area that is particularly straightforward. The
following jPetstore validation code provides an example of a
typical Spring Validator:

[prettify]public class AccountValidator implements Validator {
...
 public void validate(Object obj, Errors errors) {
   ValidationUtils.rejectIfEmpty(errors, "firstName", \\
              "FIRST_NAME_REQUIRED", "First name is required.");
   ValidationUtils.rejectIfEmpty(errors, "lastName", \\
               "LAST_NAME_REQUIRED", "Last name is required.");
   ValidationUtils.rejectIfEmpty(errors, "email", \\
                "EMAIL_REQUIRED", "Email address is required.");
   ValidationUtils.rejectIfEmpty(errors, "phone", \\
               "PHONE_REQUIRED", "Phone number is required.");
   ValidationUtils.rejectIfEmpty(errors, "address1", \\
                "ADDRESS_REQUIRED", "Address (1) is required.");
   ValidationUtils.rejectIfEmpty(errors, "city", \\
               "CITY_REQUIRED", "City is required.");
   ValidationUtils.rejectIfEmpty(errors, "state", \\
               "STATE_REQUIRED", "State is required.");
   ValidationUtils.rejectIfEmpty(errors, "zip", \\
               "ZIP_REQUIRED", "ZIP is required.");
   ValidationUtils.rejectIfEmpty(errors, "country", \\
               "COUNTRY_REQUIRED", "Country is required.");
 }
...
}
[/prettify]

While providing a functional example for a sample application, a
major drawback to this approach is that the logic is designed to
operate on the entire HTML form. An unfortunate consequence is that
validation of an individual form field, required to support Ajax
validation, is not possible. With a small amount of refactoring,
this drawback can be avoided. The resulting code is:

[prettify]...
public void validate(Object obj, Errors errors) {

   Account account = (Account) obj;

   validateFirstName(account.getFirstName(), errors);
   validateLastName(account.getLastName(), errors);
   validateEmail(account.getEmail(), errors);
   validatePhone(account.getPhone(), errors);
   validateAddress1(account.getAddress1(), errors);
   validateCity(account.getCity(), errors);
   validateState(account.getState(), errors);
   validateZip(account.getZip(), errors);
   validateCountry(account.getCountry(), errors);
}
...
public void validateFirstName(String firstName, Errors errors) {
   ValidationUtils.rejectIfEmpty(errors, "firstName", \\
              "FIRST_NAME_REQUIRED", "First name is required.");
}

public void validateLastName(String lastName, Errors errors) {
   ValidationUtils.rejectIfEmpty(errors, "lastName", \\
              "LAST_NAME_REQUIRED", "Last name is required.");
}
...
[/prettify]

By casting the parameter obj into an instance of
the form backing object and extracting the logic of the original
validate() method into separate methods intended to
validate a single form field, this seemingly cosmetic refactoring
provides a handful of benefits. First, the new code results in a
number of short, highly cohesive, easy-to-read methods. The logic
to validate the first-name input field is easily and quickly found
within the validateFirstName() method instead of being
scattered throughout the original long "validate
everything" method. Second, this level of organization and
structure will pay off should your HTML forms or their validation
logic grow in complexity and/or length. Third, and most
importantly, because there are methods to validate individual input
fields, Ajax validation can now be supported.

When a form submission is received, Spring's form handling
process works by first instantiating an instance of the form
backing object. Next, a form input element is bound to the backing
object by using reflection to call the appropriate setter method
with the form input value passed as an argument. This binding
process is repeated for each input element. Finally, with the
backing object passed as a parameter, the validate() method on a
validator is called. Because an Ajax validation request is not a
normal form submission and contains only a form input ID and value,
Spring's normal process can't be used and the instantiation and
binding must be done "manually." However, instead of
invoking the Validator.validate() method, which expects an instance
of the form backing object, we will invoke the validation method
for an individual field. The following code, located in the
AccountValidator class and exposed to the
client, performs these manual instantiation, binding, and
validation invocation steps:

[prettify]/**
 * Get the validation message for an individual
 * input field of a model object.
 *
 * @param modelObject The object to validate against.
 * @param formInputId The id attribute of the form input field.
 * @param formInputValue The input value to be validated.
 * @return The validation message.
 */
public String getInputFieldValidationMessage(String formInputId, String formInputValue) {

 String validationMessage = "";

 try
 {
   Object formBackingObject = new Account();
   Errors errors = new BindException(formBackingObject, "command");

   formInputId = formInputId.split("\\.")[1]; // Ignore the preceding "command." portion of the id
   String capitalizedFormInputId = StringUtils.capitalize(formInputId);

   // Invoke the set[formInputId] method on the Account instance
   String accountMethodName = "set" + capitalizedFormInputId;
   Class setterArgs[] = new Class[] { String.class };
   Method accountMethod = formBackingObject.getClass().getMethod(accountMethodName, setterArgs);
   accountMethod.invoke(formBackingObject, new Object[] { formInputValue });

   // Invoke the validate[formInputId] method of the AccountValidator instance
   String validationMethodName = "validate" + capitalizedFormInputId;
   Class validationArgs[] = new Class[] { String.class, Errors.class };
   Method validationMethod = getClass().getMethod(validationMethodName, validationArgs);
   validationMethod.invoke(this, new Object[] { formInputValue, errors });

   validationMessage = getValidationMessage(errors, formInputId);
 }
 catch (Exception e)
 {
   // Handle appropriately for your application
   System.out.println("New code exception: " + e);
 }

 return validationMessage;
}
[/prettify]

If getInputFieldValidationMessage were passed a
formInputId of username, the preceding code would call
setUsername() to bind the formInputValue parameter to
a newly instantiated instance of Account. Next,
validateUsername would be invoked on the
AccountValidator class. Finally, the following
getValidationMessage() would be used to take advantage
of Spring's underlying form validation messaging mechanism and
retrieve the actual text that is returned to the browser and
presented to the user.

[prettify]/**
 * Get the FieldError validation message from the underlying MessageSource for the given fieldName.
 *
 * @param errors The validation errors.
 * @param fieldName The fieldName to retrieve the error message from.
 * @return The validation message or an empty String.
 */
protected String getValidationMessage(Errors errors, String fieldName)
{
 String message = "";

 FieldError fieldError = errors.getFieldError(fieldName);

 if (fieldError != null)
 {
  message = messageSource.getMessage(fieldError.getCode(), null,
                    "This field is invalid", Locale.ENGLISH);
 }

 return message;
}
[/prettify]

Ajax Using DWR

Ajax has quickly matured to a state where many open source Ajax
frameworks exist. You'll be doing yourself a favor by using one of
these frameworks instead of creating your own implementation.
Direct Web Remoting (DWR), a
java.net project created by
Get Ahead, is an outstanding
choice. Being easy to use while providing advanced features, DWR is
well documented and straightforward to integrate into your
application. Well designed, DWR works by dynamically generating
JavaScript based on Java classes. Using a servlet and the necessary
JavaScript infrastructure, JavaScript calls made in the browser are
transparently sent to the server, invoked on the Java class, with
the results sent back to the browser and available in JavaScript.
Because DWR is well documented, only a brief description of the
steps taken to integrate it into the sample application are
presented. For a more complete explanation of DWR, I refer you to
the design
overview
and getting started
sections of the project's website.

The following steps were used to integrate DWR into the sample
application:

  1. Download dwr.jar from the project's download page. This
    article uses version 1.1.4.

  2. Add the downloaded dwr.jar to the sample web application
    lib directory.

  3. Include the following servlet definition and mapping in the
    web.xml:

    [prettify]<servlet>
       <servlet-name>dwr-invoker</servlet-name>
       <display-name>DWR Servlet</display-name>
       <servlet-class>uk.ltd.getahead.dwr.DWRServlet</servlet-class>
       <init-param>
           <param-name>debug</param-name>
           <param-value>true</param-value>
       </init-param>
    </servlet>
    ...
    <servlet-mapping>
        <servlet-name>dwr-invoker</servlet-name>
        <url-pattern>/dwr/*</url-pattern>
    </servlet-mapping>
    
    [/prettify]
  4. Because the sample application uses the Spring framework for
    validation logic, we need some way to tell DWR to instantiate
    the Spring validation bean classes and expose them through
    JavaScript. Fortunately, DWR provides Spring integration out of the
    box through SpringCreators. The DWR configuration
    file, named dwr.xml and located in the same
    directory as web.xml, is as follows:

    [prettify]<!DOCTYPE dwr PUBLIC
        "-//GetAhead Limited//DTD Direct Web Remoting 1.0//EN"
        "http://www.getahead.ltd.uk/dwr/dwr10.dtd">
    <dwr>
        <allow>
            <create creator="spring" javascript="AccountValidatorJS">
                  <param name="beanName" value="accountValidator"/>
                  <include method="getFieldInputValidationMessage"/>
            </create>
        </allow>
    </dwr>
    
    [/prettify]

    The file instructs DWR to create a JavaScript object named
    AccountValidatorJS. With DWR handling all of the
    details, when the client calls a JavaScript function on the
    AccountValidatorJS object, a server-side Java method
    of the same name is invoked on Spring's instance of the
    AccountValidator class. This is how server-side logic,
    in this case validation logic, is exposed to the client through
    Ajax.

Controlling the Process with JavaScript

With the server-side validation logic and Ajax communication
framework in place, the third and final component is to modify the
web tier to support the Ajax validation process. Each page
containing a form that is to be Ajax validated needs to have a
small amount of JavaScript infrastructure added. An example of this
infrastructure is listed below:

[prettify]...
 <script type='text/javascript' src='/jpetstore/dwr/engine.js'></script>
 <script type='text/javascript' src='/jpetstore/dwr/util.js'></script>
 <script type='text/javascript' src='/jpetstore/dwr/interface/AccountValidatorJS.js'></script>
 <script language="JavaScript">

 // Swallow errors and warnings from DWR; handle appropriately in your app
 DWREngine.setErrorHandler(null);
 DWREngine.setWarningHandler(null);

 function validateAccountInputField(element)
 {
   var id = element.id;
   var value = element.value;
   AccountValidatorJS.getInputFieldValidationMessage(id, value, {
           callback:function(dataFromServer) {
                   setInputFieldStatus(element.id, dataFromServer);
           }
   });
 }

 function setInputFieldStatus(elementId, message)
 {
    var id = "" + elementId + "Error";
    document.getElementById(id).innerHTML = message;
 }
 </script>
...
[/prettify]

After including two core DWR scripts on the first two lines, the
third line includes the generated AccountValidatorJS
proxy object. While the first two scripts will typically be
included on any page in which you use DWR, the third line is
specific to which server-side Java object you intend to take
advantage of and will vary from page to page.

Next, the the global error and warning
handlers
are set to null, thereby swallowing all DWR errors and
warnings. While acceptable for the purposes of this article, this
is obviously not sufficient for enterprise-level software and I
strongly suggest a different design for for your production
applications.

The validateAccountInputField() function is the
workhorse of the client-side validation. By accepting a reference
to the form input element that is to be validated, the
AccountValidatorJS proxy object is used to transmit
the input field's id and value to the
server for validation. Although the syntax is cryptic and hard to
read, the third parameter to the
AccountValidatorJS.getInputFieldValidationMessage()
function instructs DWR to invoke the
setInputFieldStatus() callback function when the
response from the server is available. At that time, the
setInputFieldStatus() function performs the dynamic
display and update of the on-screen validation message. By
appending Error to the element's id, a
reference to the span used for visual display is
obtained and its innerHTML is updated with the content
of the response validation message.

Finally, validateAccountInputField() needs some way
of being invoked when the user alters an input field. This is
accomplished by adding an onChange() event listener to
each form input you wish to Ajax validate. A snippet from an
example form is shown below:

[prettify]...
  <form action="<c:url value="/shop/newAccount.do"/>" method="post">
  ...
  <TR bgcolor="white">
       <TD><font color="red">* </font>First name:</TD>
       <TD>
         <spring:bind path="accountForm.account.firstName">
                 <input type="text"
                        id="<c:out value="${status.expression}"/>"
                        value="<c:out value="${status.value}"/>"
                        onChange="validateAccountInputField(this);"
                />
                <span id="<c:out value="${status.expression}"/>Error" class="error">
                      <c:out value="${status.errorMessage}"/>
                </span>
        </spring:bind>
      </TD>
 </TR>
 ...
 </form>
...
[/prettify]

While the use of Spring's form-handling capabilities will be
unusual to those not familiar with Spring MVC, the rest is a
typical HTML form with a span located next to the
input field used to display the validation message. The use of an
onChange() event listener will invoke
valdiateAccountInputField() when a user changes the
value of this input field. Using this to pass a
reference of itself to the validateAccountInputFiled()
function, the code is generic for every input field and can quickly
be added to to all of your forms.

Figure 1 demonstrates the web tier UI after a user has modified
the form. In this particular case, the user filled out the form and
subsequently removed all input except for the user ID field. As the
user removed the input and the browser focus shifted to a different
input, the Ajax validation was invoked and a message indicating
that that field was required was dynamically displayed. Of
particular interest is the user ID input field, with the dynamic
message that that username is not available.

Display of dynamic validation messages
Figure 1. Display of dynamic validation messages

Conclusion

Using the jPetStore sample application, this article discussed
and demonstrated a design for a generic and reusable Ajax form
validation solution. Using existing open source projects and
leveraging your applications validation logic, the development time
and complexity required to implement this solution into your
applications is minimal. After setting up the necessary
infrastructure (and possibly some minor refactoring to existing
applications), the largest effort will probably be simply adding
onChange() event listeners to the HTML form input
elements you'd like to validate via Ajax. While this article made use
of the Spring and DWR frameworks, nothing about Ajax or the Ajax
validation concepts presented here are tied to any particular tool,
framework, or language, and implementations can be created in any
way that fits your particular technical or business
requirements.

Resources

width="1" height="1" border="0" alt=" " />
Eric Spiegelberg is a Minneapolis-based Java/EE consultant specializing in Spring, Hibernate, and web-based software development.
Related Topics >> Programming   |   

Comments

very good explanation for

very good explanation for Ajax integration with spring