AJAX validation with Spring without changing any java-code
client and server side validation. New frameworks like Spring and JSF have no
client side validation (yet). I read some things about commons validator (the
one used in Struts) in combination with Spring. But we reached the ajax-era, so
the javascript alert boxes should be used for debugging only.
This article will explain how to create a plain old Spring
validator and changing that validator to an ajax-validator without changing
much code.
Setting up normal
validation in Spring
I assume you have some basic knowledge of the Spring web-mvc
framework, when you don’t have this basic knowledge please read this article I published earlier.
Set up a Spring
project in your favorite IDE.
The first step is our data-model. It’s a very sophisticated
personal information manager:

Create a simple bean with getters and setters for name and
city (nl.amis.Contact)
The next step is a SimpleFormController. Let’s call it
ContactFormController. Create the class, extend SimpleFormController and do not
override any methods (it’s not necessary for our example).
Now create a class ContactValidator and implement the
interface Validator:
package
nl.amis;
import
org.springframework.validation.Errors;
import
org.springframework.validation.Validator;
public
class ContactValidator implements Validator {
public boolean supports(Class clazz) {
return clazz.equals(Contact.class);
}
public void validate(Object command, Errors
errors) {
Contact contact = (Contact) command;
if
(contact.getName().equals("")) {
errors.rejectValue("name",
"invalid.name", "Name is a required field");
}
if
(contact.getCity().equals("")) {
errors.rejectValue("city", "invalid.city",
"City is a required field");
}
}
}
The mehod supports tells us the validator can validate
objects of the class Contact (we use clazz instead of class because class is a
reserved word). The actual validator is implemented in the method validate. We
do some simple validation on both fields, they must not be empty. The first
argument of errors.rejectValue is the field name, the second the message key
and the last the default error message
(when no key is found).
And now the inevitable xml to wire all the components
togheter:
<?xml
version="1.0"
encoding="UTF-8"?>
<!DOCTYPE
beans PUBLIC "-//SPRING//DTD
BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean
name="/contact.form"
class="nl.amis.ContactFormController">
<property
name="formView" value="form"
/>
<property
name="successView" value="success"
/>
<property
name="commandClass" value="nl.amis.Contact"
/>
<property
name="validator">
<ref
bean="contactValidator" />
</property>
</bean>
<bean
name="contactValidator" class="nl.amis.ContactValidator"
/>
<bean
id="jspViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property
name="viewClass"
value="org.springframework.web.servlet.view.JstlView"
/>
<property
name="prefix" value="/WEB-INF/jsp/"
/>
<property
name="suffix" value=".jsp"
/>
</bean>
</beans>
Nothing specials happens here, we only added the validator
property to the bean we already knew. Now we have to create form.jsp and
success.jsp and place them in WEB-INF\jsp
Create your own success.jsp and use the following code for
form.jsp:
<%@
taglib prefix="spring"
uri="http://www.springframework.org/tags"%>
<%@
taglib prefix="c"
uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<head></head>
<body>
<form
method="post">
<spring:bind
path="command.name">
name: <input
type="text" name="${status.expression}"
value="${status.value}" />
<c:out
value="${status.errorMessage}"/><br/>
</spring:bind>
<spring:bind
path="command.city">
city: <input
type="text" name="${status.expression}"
value="${status.value}" />
<c:out
value="${status.errorMessage}"/><br/>
</spring:bind>
<input
type="submit" value="validate"/>
</body>
</html>
It’s
just a html form with fields for name and city. The input tags are surrounded
by <spring:bind/> tags. These tags bind the values to the variables of
the command object (the default name for command is command, you can change
this name by setting the commandName property in your SimpleFormController
bean)
The
form.jsp is also used when there are validation errors, these errors are
printed at the location of status.errorMessage and the corresponding field.
Compile
your application, deploy it and visit contact.form (I used the url pattern
*.form for the Spring servlet mapping). Your page should display the following
form:

click the validate button (because we want an invalid form) and the validation
errors appear next to the fields:

Creating
To
create
validation we have to remove the <spring:bind/> tags from our form and save it in the root
directory of your project (usually something like webapp)
<form
method="post"
action="contact.form">
<table
border="0"
cellpadding="4"
cellspacing="0"
width="540">
<tr>
<td
width="80"><b>name</b></td>
<td
width="150"><input
type="text" name="name"
id="name"/></td>
<td
width="310"><div
id="nameError"/></td>
</tr>
<tr>
<td><b>city</b></td>
<td><input
type="text" name="city"
id="city"/></td>
<td><div
id="cityError"/></td>
</tr>
<tr><td
colspan="3"
align="center">
<input
type="button" onclick="postForm();"
value="validate"/></td></tr>
</table>
</form>
I also added a table and a stylesheet to
the form to make it look less crappy. You probably also noticed the id
attributes at the input tags and the new div’s with an id attribute that ends
with Error. The div’s are to display the error messages. The id attribute at
the input tags are needed because I want to use document.getElementById. It is
possible to iterate through all the form fields with JavaScript and the div’s
could also be removed, but this makes it a lot easier to explain.
In the head part of your html add the following code:
<script
type="text/javascript" src="js/xhr.js"></script>
<script
language="JavaScript">
function postForm(){
var formString="name="+
document.getElementById(‘name’).value
+"&city=" + document.getElementById(‘city’).value;
document.getElementById(‘nameError’).innerHTML="";
document.getElementById(‘cityError’).innerHTML="";
loadXMLDoc("contact.form",formString);
}
</script>
<link type="text/css"
rel="stylesheet" href="css/std.css"
/>
The xhr.js is a file to make the XMLHttpRequest and can be
downloaded here. Because Spring expects forms to be posted we have to put
the form in a String (this is where document.getElementById is very handy)
After this we clear the error messages (it is possible that
the users submits the form for the second time and fixed some error).
loadXMLDoc makes the actual XMLHttpRequest.
The xhr.js is the same file that’s always used in all the
guides with some minor adaptions. I
changed the method signature of loadXMLDoc, I added the form variable. This is the part that is added to post the
form:
req.open("POST",
url, true);
req.setRequestHeader("Content-Type","application/x-www-form-urlencoded;");
req.send(form);
And the callback executes the response as javascript (with eval(req.responseText);). This
is a bit tricky and it is probably better and safer when you make a system
where no eval is needed, but it’s an example and reduces the amount of code
needed to explain everything to you.
Don’t forget to copy success.jsp to your root directory
because we can’t use the old one anymore.
Create a new form.jsp in your WEB-INF/jsp directory:
<%@
taglib prefix="spring"
uri="http://www.springframework.org/tags"%>
<%@
taglib prefix="c"
uri="http://java.sun.com/jsp/jstl/core"%>
<spring:bind
path="command.name">
<c:if
test="${not
empty status.errorMessage}">
document.getElementById(‘${status.expression}Error’).innerHTML=’<img
align="absmiddle"
src="img/arrow2.png"> <c:out
value="${status.errorMessage}"
/>‘;
</c:if>
</spring:bind>
<spring:bind
path="command.city">
<c:if
test="${not
empty status.errorMessage}">
document.getElementById(‘${status.expression}Error’).innerHTML=’<img
align="absmiddle"
src="img/arrow2.png"> <c:out
value="${status.errorMessage}"
/>‘;
</c:if>
</spring:bind>
We have to use the bind tags again, because we need the
error message inside these tags. With an if statement we check if there exist
an errorMessage. If there is an error message the validation of the
corresponding field failed and we have to display an error message inside the
div. If there is no error message no javascript will be generated. If there is
no error message at all the success.jsp is loaded. You also see an <img>
tag inside the javascript, the image can be downloaded here.
So far everything is pretty clean and no strange tricks are
needed. Except for success.jsp unfortunately, we have to hardcode an url inside
the javascript:
document.location.href="success.jsp";
This line of javascript loads the old success page as if
nothing happened with
validation.
No deploy your application again and visit form.jsp (NOT
contact.form!) and hit the validate button:

When you type some characters in one of the fields and hit
validate again one red arrow should
disappear.
Conclusion
I think this is a really nice way to have
might even be better than the normal spring validation because you don’t need
the <spring:bind> tags in your forms anymore and with some effort you
don’t need the div’s for the errors and the id attributes in the form fields.
Another remark is that you hardcoded the url for the
succesView in your page. You can work around this issue by creating something
like a finalView as variable in your bean and use it in the success javascript.
This diagram summarizes what happened. I moved all the
action to the background where it is invisible for the user. On top of that we
created two new pages with some javascript in it.


29/5/2006 - 12:10 pm
I’ve pushed your idea a bit further. The simplicity of ajax-validation could be taken to extreme by requiring end-user(developer) only to add “implement LiveValidator” to turn ajax-validation on. Any ideas? Link to LiveValidator idea is at http://ahtik.com/blog/2006/05/28/livevalidator-for-ajaxified-springframework/
7/7/2006 - 11:33 am
Very nice explanation…. Keep it up….
I thank you very much…….
Wish u all success…
13/2/2007 - 1:09 pm
Hi
I could not able to download the js file , please send to me instead of downloading ..
14/7/2007 - 3:33 pm
Hi,
Pls help me where can i found a good help website about ajax?
thnx