STRUTS: Validator Framework - Part 2
Posted On August 27, 2007 by Sneha Philipose filed under
Validator framework requires two XML files, namely,
1. validator-rules.xml; and
2. validation.xml.
(We are using struts1.1)
These files are already available in WEB-INF folder, along with web.xml and struts-config.xml. So, no special installation is necessary, to use the Validator framework. The validator-rules.xml file provides the rules for the ready-made validations available in the framework. The validation.xml file is meant for specifying our requirements. It is advisable not to tamper with validator-rules.xml (just as we need not meddle with web.xml file).
The Validator framework provides ready-made facility for the following:
1. RequiredField validation;
2. Regular-Expression validation (mask);
3. email validation;
4. credit-card validation;
5. date validation;
6. minvalue validation;
7. maxvalue validation;
8. range validation;
9. byte, short, int, long validation; and
10. float, double validation.
When we use the Validator Framework, we get the bonus of client-side JavaScript validation also, automatically, with messagebox and all! Otherwise, we would have to write laborious and clumsy JavaScript functions for routine validations. Client-side validation, though not very reliable, saves the round-trip time and so is better appreciated by clients. However, the framework gives server-side validation always.
Let us now take up a comprehensive demo for illustration. We shall name this as 'validsapp'! The example will be easy to follow, since we have already covered the usual pattern in our previous lesson. Only a few changes are required.
1. The validsForm.java is derived from ValidatorForm and not from ActionForm;
2. Therefore we have to import 'org.apache.struts.validator.*';
3. Since the framework takes care of form-validation, as per the requirements specified by us in validation.xml file, there is no need to provide validate method in validsForm class file;
4. We have to make suitable entries in 'validation.xml' file available in WEB-INF\ folder;
5. We should not forget to make entries for form-bean and action-mapping in struts-config.xml file; and
6. Finally, we have to add a few key-value pairs for the error messages in application.properties file in WEB-INF\classes\resources folder, as before.
Apart from these, the other files follow the usual pattern. As the focus of this second part of the tutorial is on the method of using Validator framework, let us skip the helperbean and resultbean. Thus, this demo requires just two jsp files – validsSubmit.jsp and validsOutput.jsp – and two java classes – validsForm.java and validsAction.java.
As before, we rename 'struts-blank' as 'validsapp' and create 'validspack' folder in validsapp\WEB-INF\classes\' folder. Readers may refer to part 1 for the exact procedure.
We now create a folder called 'validspack' in 'g:\mydir'.
cd to g:\mydir\validspack'
set path=c:\windows\command;
d:\jdk1.4.2\bin
set classpath=g:\mydir;
c:\quick\struts;
e:\tomcat41\common\lib\servlet.jar
We create the following files in 'g:\mydir\validspack' folder.
1. validsSubmit.jsp;
2. validsForm.java;
3. validsAction.java; and
4. validsOutput.jsp.
The files have been given below, in that order. Carefully note the two following lines in validsSubmit.jsp:
onsubmit="return validateValidsForm(this);">
<html:javascript formName="validsForm" />
(The above two lines enable JavaScript validation on client-side, when we use the Validator framework)
// code-1
// g:\mydir\validspack\validsSubmit.jsp
<%@ taglib prefix="html"
uri="/WEB-INF/struts-html.tld" %>
<%@ taglib prefix="bean"
uri="/WEB-INF/struts-bean.tld" %>
<%@ taglib prefix="logic"
uri="/WEB-INF/struts-logic.tld" %>
<html:html>
<body bgcolor=pink>
<html:errors />
<html:form action="/valids"
name="validsForm"
type="validspack.validsForm"
onsubmit="return validateValidsForm(this);">
NAME:
<html:text property="name"/> <br>
PASSWORD:<html:text property="password"/> <br>
MAIL-ID
<html:text property="mail_id" /> <br>
DATE: <html:text property="date"/> <br>
PINCODE:<html:text property="pincode"/> <br>
<html:submit/>
</html:form>
<html:javascript formName="validsForm" />
</body>
</html:html>
*******************************************
// code-2
// g:\mydir\validspack\validsForm.java
package validspack;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.apache.struts.validator.*;
public class validsForm extends ValidatorForm
{
String name = null;
String password = null;
String mail_id = null;
String date = null;
String pincode = null;
public String getName()
{ return name; }
public void setName(String a)
{ name=a; }
//----------------------------
public String getPassword()
{ return password; }
public void setPassword(String b)
{ password=b; }
//------------------------------
public String getMail_id()
{ return mail_id; }
public void setMail_id(String c)
{ mail_id=c; }
//----------------------------
public String getDate()
{ return date; }
public void setDate(String d)
{ date=d; }
//-------------------------------
public String getPincode()
{ return pincode; }
public void setPincode(String e)
{ pincode=e; }
//-------------------------------
public void reset(ActionMapping mapping,
HttpServletRequest request)
{
name = null;
password = null;
mail_id = null;
date = null;
pincode = null;
}
}
============================================
// code-3
// g:\mydir\validspack\validsAction.java
package validspack;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class validsAction extends Action
{
public ActionForward execute
(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
validsForm validsform =(validsForm) form;
String s1 = validsform.getName();
String s2 = validsform.getPassword();
String s3 = validsform.getMail_id();
String s4 = validsform.getDate();
String s5 = validsform.getPincode();
if(s1.length()!=0)
{
String r =s1+"<br>"+
s2+"<br>"+s3+"<br>"+
s4+"<br>"+s5;
HttpSession session = request.getSession();
session.setAttribute("result",r);
return(mapping.findForward("success"));
}
else
{
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("errors.global"));
saveErrors(request,errors);
return(mapping.findForward("failure"));
}
}
}
=====================================
// code-4
// g:\mydir\validspack\validsOutput.jsp
<html>
<body bgcolor=lightgreen>
<%
String r=
(String)session.getAttribute("result");
out.println(r);
%>
</body>
</html>
==========================================
We are now ready to compile and deploy. We are in g:\mydir\validspack. Check the path (c:\windows\command;d:\jdk1.4.2\bin). Checkup classpath.
(g:\mydir;c:\quick\struts.jar;
e:\tomcat41\common\lib\servlet.jar)
>javac *.java
We now copy validsForm.class and validsAction.class to:
'e:\tomcat41\webapps\validsapp\WEB-INF\classes\validpack' folder.
We copy validsSubmit.jsp and validsOutput.jsp to :
'e:\tomcat41\webapps\validsapp' folder.
We have to make the following entries in:
e:\tomcat41\weebapps\validsapp\WEB-INF\struts-config.xml file.
*******************************************
// code-5--
end sample -->
<form-bean
name="validsForm"
type="validspack.validsForm" >
</form-bean>
</form-beans>
------
end samples -->
<action path="/valids"
input="/validsSubmit.jsp"
name="validsForm"
type="validspack.validsAction"
scope="session"
validate="true">
<forward name="success"
path="/validsOutput.jsp" />
<forward name="failure"
path="/validsSubmit.jsp" />
</action>
</action-mappings>
*****************************************
As these are exactly the same pattern as in part 1, a detailed explanation can be skipped. Let us devote more attention to the crucial entries in validation.xml in 'e:\tomcat41\webapps\validsapp\WEB-INF' folder.
--// code-6
end example form -->
<form name="validsForm">
<field property="name"
depends="required">
<arg0 key="validsForm.name" />
</field>
<field property="password"
depends="required,minlength,mask">
<arg0 key="validsForm.password" />
<var>
<var-name>minlength</var-name>
<var-value>6</var-value>
</var>
<var>
<var-name>mask</var-name>
<var-value>^[0-9a-zA-Z]*$</var-value>
</var>
</field>
<field property="mail_id"
depends="required,email">
<arg0 key="validsForm.mail_id" />
</field>
<field property="date"
depends="required,date">
<arg0 key="validsForm.date" />
<var>
<var-name>datePattern</var-name>
<var-value>MM/dd/yyyy</var-value>
</var>
</field>
<field property="pincode"
depends="required,maxlength,mask">
<arg0 key="allvalidsForm.pincode" />
<var>
<var-name>maxlength</var-name>
<var-value>6</var-value>
</var>
<var>
<var-name>mask</var-name>
<var-value>^\d{5}\d*$</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
==============================================
And finally, we add the following lines in e:\tomcat41\webapps\validsapp\WEB-INF\classes\
resources\application.properties.
*******************************************
// code-7
# -- standard errors --
errors.header=<UL>
errors.prefix=<LI>
errors.suffix=</LI>
errors.footer=</UL>
# -- validator --
errors.invalid={0} is invalid.
errors.maxlength=pincode can not be greater than 6 characters.
errors.minlength=password can not be less than 6 characters.
errors.range={0} is not in the range {1} through {2}.
errors.required={0} is required.
errors.byte={0} must be a byte.
errors.date={0} is not a date.
errors.double={0} must be a double.
errors.float={0} must be a float.
errors.integer={0} must be an integer.
errors.long={0} must be a long.
errors.short={0} must be a short.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
# -- other --
errors.cancel=Operation cancelled.
errors.detail={0}
errors.general=The process did not complete. Details should follow.
errors.token=Request could not be completed. Operation is not in sequence.
# -- welcome --
welcome.title=Struts Blank Application
welcome.heading=Welcome!
welcome.message=To get started on your own application, copy the struts-blank.war to a new WAR file using the name for your application. Place it in your container's "webapp" folder (or equivalent) and let your container auto-deploy the application. Edit the skeleton configuration files as needed, restart your container and you are on your way! (You can find the application.properties file with this message in the /WEB-INF/src/java/resources folder.)
#-----------------------------------------
errors.global="NO NAME HAS BEEN GIVEN"
validsForm.name=NAME
validsForm.password=PASSWORD
validsForm.mail_id=MAIL_ID
validsForm.date=DATE
validsForm.pincode=PINCODE
************************************************
We shall first run the demo and then have some explanation for entries in the validation.xml file.
We open another command window and cd to e:\tomcat41\bin.
Then set JAVA_HOME=D:\JDK1.4.2
>startup
Start the browser and type the URL as 'http://localhost:8080/validsapp/validsSubmit.jsp'
If all goes well, we will get the submit form. (If we get a lot of JavaScript along with the controls, it means that we have made some mistakes in the XML files.)
If we submit the form, without making any entries, we will get a messagebox as shown in figure 1. This is the client-side Required-Field validation. It is self-explanatory.

For the password, we have specified three conditions. Namely, it should not be blank, must not have less than six characters and finally we have given a regular expression, which means that the characters can be lowercase or uppercase or numerals (i.e.) no special characters are allowed. See figure 2.

We can test this for error one by one after putting some letters in all the fields, because, specific validation is done only after the required field condition in all the controls is fulfilled.
The error condition for wrong mail-id can be easily simulated by giving it as tom @ dom.com (We are not supposed to provide space either before or after @). Nor can we use capital letters. Refer figure 3.

The date pattern has been given as 'mm/dd/yyyy'. So, if we type the date as '31/01/2005', we will get error message. Finally, for pin code, we have provided a regular expression as well as maxlength condition.
If all these are apparently correct, we can provide further validation code in action class, which is known as 'action-validation'. If due to some reason, there is no client-side JavaScript validation, we get server-side validation messages for all the above conditions. Refer figure 4.

(Sometimes, the results of client-side validation may differ from Server-side validation. As Husted points out, it may be confusing but that is how things stand now.)
Reference Books:
1. STRUTS IN ACTION by TED HUSTED and OTHERS. (The chapter on Validator framework.. chapter 12... has been co-authored by David Winterfeldt, creator of the Validator framework and so is authoritative). (Manning/DreamTech)
2. Programming Jakarata Struts by Chuck Cavaness. Chapter 11. (OReilly)
3. STRUTS SURVIVAL GUIDE by Srikanth Shenoy.
1. validator-rules.xml; and
2. validation.xml.
(We are using struts1.1)
These files are already available in WEB-INF folder, along with web.xml and struts-config.xml. So, no special installation is necessary, to use the Validator framework. The validator-rules.xml file provides the rules for the ready-made validations available in the framework. The validation.xml file is meant for specifying our requirements. It is advisable not to tamper with validator-rules.xml (just as we need not meddle with web.xml file).
The Validator framework provides ready-made facility for the following:
1. RequiredField validation;
2. Regular-Expression validation (mask);
3. email validation;
4. credit-card validation;
5. date validation;
6. minvalue validation;
7. maxvalue validation;
8. range validation;
9. byte, short, int, long validation; and
10. float, double validation.
When we use the Validator Framework, we get the bonus of client-side JavaScript validation also, automatically, with messagebox and all! Otherwise, we would have to write laborious and clumsy JavaScript functions for routine validations. Client-side validation, though not very reliable, saves the round-trip time and so is better appreciated by clients. However, the framework gives server-side validation always.
Let us now take up a comprehensive demo for illustration. We shall name this as 'validsapp'! The example will be easy to follow, since we have already covered the usual pattern in our previous lesson. Only a few changes are required.
1. The validsForm.java is derived from ValidatorForm and not from ActionForm;
2. Therefore we have to import 'org.apache.struts.validator.*';
3. Since the framework takes care of form-validation, as per the requirements specified by us in validation.xml file, there is no need to provide validate method in validsForm class file;
4. We have to make suitable entries in 'validation.xml' file available in WEB-INF\ folder;
5. We should not forget to make entries for form-bean and action-mapping in struts-config.xml file; and
6. Finally, we have to add a few key-value pairs for the error messages in application.properties file in WEB-INF\classes\resources folder, as before.
Apart from these, the other files follow the usual pattern. As the focus of this second part of the tutorial is on the method of using Validator framework, let us skip the helperbean and resultbean. Thus, this demo requires just two jsp files – validsSubmit.jsp and validsOutput.jsp – and two java classes – validsForm.java and validsAction.java.
As before, we rename 'struts-blank' as 'validsapp' and create 'validspack' folder in validsapp\WEB-INF\classes\' folder. Readers may refer to part 1 for the exact procedure.
We now create a folder called 'validspack' in 'g:\mydir'.
cd to g:\mydir\validspack'
set path=c:\windows\command;
d:\jdk1.4.2\bin
set classpath=g:\mydir;
c:\quick\struts;
e:\tomcat41\common\lib\servlet.jar
We create the following files in 'g:\mydir\validspack' folder.
1. validsSubmit.jsp;
2. validsForm.java;
3. validsAction.java; and
4. validsOutput.jsp.
The files have been given below, in that order. Carefully note the two following lines in validsSubmit.jsp:
onsubmit="return validateValidsForm(this);">
<html:javascript formName="validsForm" />
(The above two lines enable JavaScript validation on client-side, when we use the Validator framework)
// code-1
// g:\mydir\validspack\validsSubmit.jsp
<%@ taglib prefix="html"
uri="/WEB-INF/struts-html.tld" %>
<%@ taglib prefix="bean"
uri="/WEB-INF/struts-bean.tld" %>
<%@ taglib prefix="logic"
uri="/WEB-INF/struts-logic.tld" %>
<html:html>
<body bgcolor=pink>
<html:errors />
<html:form action="/valids"
name="validsForm"
type="validspack.validsForm"
onsubmit="return validateValidsForm(this);">
NAME:
<html:text property="name"/> <br>
PASSWORD:<html:text property="password"/> <br>
MAIL-ID
<html:text property="mail_id" /> <br>
DATE: <html:text property="date"/> <br>
PINCODE:<html:text property="pincode"/> <br>
<html:submit/>
</html:form>
<html:javascript formName="validsForm" />
</body>
</html:html>
*******************************************
// code-2
// g:\mydir\validspack\validsForm.java
package validspack;
import javax.servlet.http.*;
import org.apache.struts.action.*;
import org.apache.struts.validator.*;
public class validsForm extends ValidatorForm
{
String name = null;
String password = null;
String mail_id = null;
String date = null;
String pincode = null;
public String getName()
{ return name; }
public void setName(String a)
{ name=a; }
//----------------------------
public String getPassword()
{ return password; }
public void setPassword(String b)
{ password=b; }
//------------------------------
public String getMail_id()
{ return mail_id; }
public void setMail_id(String c)
{ mail_id=c; }
//----------------------------
public String getDate()
{ return date; }
public void setDate(String d)
{ date=d; }
//-------------------------------
public String getPincode()
{ return pincode; }
public void setPincode(String e)
{ pincode=e; }
//-------------------------------
public void reset(ActionMapping mapping,
HttpServletRequest request)
{
name = null;
password = null;
mail_id = null;
date = null;
pincode = null;
}
}
============================================
// code-3
// g:\mydir\validspack\validsAction.java
package validspack;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.struts.action.*;
public class validsAction extends Action
{
public ActionForward execute
(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws IOException, ServletException
{
validsForm validsform =(validsForm) form;
String s1 = validsform.getName();
String s2 = validsform.getPassword();
String s3 = validsform.getMail_id();
String s4 = validsform.getDate();
String s5 = validsform.getPincode();
if(s1.length()!=0)
{
String r =s1+"<br>"+
s2+"<br>"+s3+"<br>"+
s4+"<br>"+s5;
HttpSession session = request.getSession();
session.setAttribute("result",r);
return(mapping.findForward("success"));
}
else
{
ActionErrors errors = new ActionErrors();
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("errors.global"));
saveErrors(request,errors);
return(mapping.findForward("failure"));
}
}
}
=====================================
// code-4
// g:\mydir\validspack\validsOutput.jsp
<html>
<body bgcolor=lightgreen>
<%
String r=
(String)session.getAttribute("result");
out.println(r);
%>
</body>
</html>
==========================================
We are now ready to compile and deploy. We are in g:\mydir\validspack. Check the path (c:\windows\command;d:\jdk1.4.2\bin). Checkup classpath.
(g:\mydir;c:\quick\struts.jar;
e:\tomcat41\common\lib\servlet.jar)
>javac *.java
We now copy validsForm.class and validsAction.class to:
'e:\tomcat41\webapps\validsapp\WEB-INF\classes\validpack' folder.
We copy validsSubmit.jsp and validsOutput.jsp to :
'e:\tomcat41\webapps\validsapp' folder.
We have to make the following entries in:
e:\tomcat41\weebapps\validsapp\WEB-INF\struts-config.xml file.
*******************************************
// code-5--
end sample -->
<form-bean
name="validsForm"
type="validspack.validsForm" >
</form-bean>
</form-beans>
------
end samples -->
<action path="/valids"
input="/validsSubmit.jsp"
name="validsForm"
type="validspack.validsAction"
scope="session"
validate="true">
<forward name="success"
path="/validsOutput.jsp" />
<forward name="failure"
path="/validsSubmit.jsp" />
</action>
</action-mappings>
*****************************************
As these are exactly the same pattern as in part 1, a detailed explanation can be skipped. Let us devote more attention to the crucial entries in validation.xml in 'e:\tomcat41\webapps\validsapp\WEB-INF' folder.
--// code-6
end example form -->
<form name="validsForm">
<field property="name"
depends="required">
<arg0 key="validsForm.name" />
</field>
<field property="password"
depends="required,minlength,mask">
<arg0 key="validsForm.password" />
<var>
<var-name>minlength</var-name>
<var-value>6</var-value>
</var>
<var>
<var-name>mask</var-name>
<var-value>^[0-9a-zA-Z]*$</var-value>
</var>
</field>
<field property="mail_id"
depends="required,email">
<arg0 key="validsForm.mail_id" />
</field>
<field property="date"
depends="required,date">
<arg0 key="validsForm.date" />
<var>
<var-name>datePattern</var-name>
<var-value>MM/dd/yyyy</var-value>
</var>
</field>
<field property="pincode"
depends="required,maxlength,mask">
<arg0 key="allvalidsForm.pincode" />
<var>
<var-name>maxlength</var-name>
<var-value>6</var-value>
</var>
<var>
<var-name>mask</var-name>
<var-value>^\d{5}\d*$</var-value>
</var>
</field>
</form>
</formset>
</form-validation>
==============================================
And finally, we add the following lines in e:\tomcat41\webapps\validsapp\WEB-INF\classes\
resources\application.properties.
*******************************************
// code-7
# -- standard errors --
errors.header=<UL>
errors.prefix=<LI>
errors.suffix=</LI>
errors.footer=</UL>
# -- validator --
errors.invalid={0} is invalid.
errors.maxlength=pincode can not be greater than 6 characters.
errors.minlength=password can not be less than 6 characters.
errors.range={0} is not in the range {1} through {2}.
errors.required={0} is required.
errors.byte={0} must be a byte.
errors.date={0} is not a date.
errors.double={0} must be a double.
errors.float={0} must be a float.
errors.integer={0} must be an integer.
errors.long={0} must be a long.
errors.short={0} must be a short.
errors.creditcard={0} is not a valid credit card number.
errors.email={0} is an invalid e-mail address.
# -- other --
errors.cancel=Operation cancelled.
errors.detail={0}
errors.general=The process did not complete. Details should follow.
errors.token=Request could not be completed. Operation is not in sequence.
# -- welcome --
welcome.title=Struts Blank Application
welcome.heading=Welcome!
welcome.message=To get started on your own application, copy the struts-blank.war to a new WAR file using the name for your application. Place it in your container's "webapp" folder (or equivalent) and let your container auto-deploy the application. Edit the skeleton configuration files as needed, restart your container and you are on your way! (You can find the application.properties file with this message in the /WEB-INF/src/java/resources folder.)
#-----------------------------------------
errors.global="NO NAME HAS BEEN GIVEN"
validsForm.name=NAME
validsForm.password=PASSWORD
validsForm.mail_id=MAIL_ID
validsForm.date=DATE
validsForm.pincode=PINCODE
************************************************
We shall first run the demo and then have some explanation for entries in the validation.xml file.
We open another command window and cd to e:\tomcat41\bin.
Then set JAVA_HOME=D:\JDK1.4.2
>startup
Start the browser and type the URL as 'http://localhost:8080/validsapp/validsSubmit.jsp'
If all goes well, we will get the submit form. (If we get a lot of JavaScript along with the controls, it means that we have made some mistakes in the XML files.)
If we submit the form, without making any entries, we will get a messagebox as shown in figure 1. This is the client-side Required-Field validation. It is self-explanatory.

For the password, we have specified three conditions. Namely, it should not be blank, must not have less than six characters and finally we have given a regular expression, which means that the characters can be lowercase or uppercase or numerals (i.e.) no special characters are allowed. See figure 2.

We can test this for error one by one after putting some letters in all the fields, because, specific validation is done only after the required field condition in all the controls is fulfilled.
The error condition for wrong mail-id can be easily simulated by giving it as tom @ dom.com (We are not supposed to provide space either before or after @). Nor can we use capital letters. Refer figure 3.

The date pattern has been given as 'mm/dd/yyyy'. So, if we type the date as '31/01/2005', we will get error message. Finally, for pin code, we have provided a regular expression as well as maxlength condition.
If all these are apparently correct, we can provide further validation code in action class, which is known as 'action-validation'. If due to some reason, there is no client-side JavaScript validation, we get server-side validation messages for all the above conditions. Refer figure 4.

(Sometimes, the results of client-side validation may differ from Server-side validation. As Husted points out, it may be confusing but that is how things stand now.)
Reference Books:
1. STRUTS IN ACTION by TED HUSTED and OTHERS. (The chapter on Validator framework.. chapter 12... has been co-authored by David Winterfeldt, creator of the Validator framework and so is authoritative). (Manning/DreamTech)
2. Programming Jakarata Struts by Chuck Cavaness. Chapter 11. (OReilly)
3. STRUTS SURVIVAL GUIDE by Srikanth Shenoy.
