Chapter 12. Validating user input

Table of Contents

Setting up the Validator plugin
Standard Built In Validations
Manually validating a form
Automatically validating a form
Using client-side Javascript validation
Writing your own pluggable validators
Conclusion
Contributors

Note

If you find this EDG documentation helpful please consider DONATING! to keep the doc alive and current.

Version:Expresso 5.6Maintainer:Raul Davidovich

Since 5.6, Expresso has integrated Struts Validator. This framework makes input validation very simple and flexible. Struts Validator can be called automatically when submitting the form, or manually from the handle State. It can also automatically generate client-side Javascript form validation. As all Struts components, Validator is configured by XML files, and it’s designed to be modular. In Expresso, Validator has been modified to use the handle state name instead of the form name for identifying the forms to validate, simplifying the use of multi-page forms.

Setting up the Validator plugin

To set up the plugin, one must add it to the struts-config.xml file, as follows:

<struts-config>
    <plug-in className="org.apache.struts.validator.ValidatorPlugIn">
      <set-property property="pathnames" value="/WEB-INF/config/validator-rules.xml,/WEB-INF/config/validation.xml" />
    </plug-in>
  </struts-config>
The pathnames property tells the plugin where to find the configuration files. You can set it to wherever you like. The validation-rules.xml file describes each rule that can be applied, saying which class will actually do the job, and the javascript code used in client-side validation. The validation.xml file sets which rules to apply to each field of each form to validate, and what response to give if the validation fails. Configuring the rules to apply for validating the forms The form validation is configured in the validation.xml file as follows:
<form-validation>
    <global />
    <formset>
      <form name="myHandleState">
        <field depends="required,minlength" property="myProp">
          <arg0 key="myProp is required" resource="false" />
          <var>
            <var-name>minlength</var-name>
            <var-value>5</var-value>
          </var>
          <msg key="myapp.errormsgs.minlengthmsg" name="minlength" />
        </field>
      </form>
    </formset>
    <formset language="fr">
      <form name="myHandleState">
        <field depends="required,minlength" property="myProp">
          <arg0 key="myProp est requis" resource="false" />
          <var>
            <var-name>minlength</var-name>
            <var-value>5</var-value>
          </var>
          <msg key="myapp.errormsgs.minlengthmsg" name="minlength" />
        </field>
      </form>
    </formset>
  </form-validation>
Each <formset> tag contains <form> tags.Each form to validate should have it’s <form> tag. The “name” property must be the same as the handle state for this form. The <form> tag contains one <field> tag for each field to check when validating the form. The “name” property must be the same as the field name (the Input) in the web page. The “depends” property defines which rules to apply to this field. Inside the <field> tag can be nested:
  • <argn> tags defining replacement parameters for any messages returned to the user. N is the order of the message to replace.

  • <var> tags with variable properties to pass to the validation functions (the maximum length of the field, a mask to apply, etc)

  • <msg> tags specifying custom message keys for validators

<argn> tags defining replacement parameters for any messages returned to the user. N is the order of the message to replace. <var> tags with variable properties to pass to the validation functions (the maximum length of the field, a mask to apply, etc) <msg> tags specifying custom message keys for validators If no replacement messages are defined, the default messages from validator-rules.xml will be used. Global constants can be inside the <global tags> and FormSet/Locale constants can be created in the <formset> tags. Constants are currently only replaced in the Field's property attribute, the Field's <var> element value attribute, the Field's <msg> element key attribute, and Field's <arg0> - <arg3> element's key attribute. The order of replacement is FormSet/Locale constants are replaced first, Global constants second, and for the <arg> elements variables are replaced last:
<global>
    <constant>
      <constant-name>zip</constant-name>
      <constant-value>^\d{5}(-\d{4})?$</constant-value>
    </constant>
  </global>
  <field depends="required,mask" property="zip">
    <arg0 key="registrationForm.zippostal.displayname" />
    <var>
      <var-name>mask</var-name>
      <var-value>${zip}</var-value>
    </var>
  </field>
The var element under a field can be used to store variables for use by a pluggable validator. These variables are available through the Field's getVar(String key) method:
<field depends="required,integer,intRange" property="integer">
    <arg0 key="typeForm.integer.displayname" />
    <arg1 key="${var:min}" name="intRange" resource="false" />
    <arg2 key="${var:max}" name="intRange" resource="false" />
    <var>
      <var-name>min</var-name>
      <var-value>10</var-value>
    </var>
    <var>
      <var-name>max</var-name>
      <var-value>20</var-value>
    </var>
  </field>

Standard Built In Validations

Validator is shipped with the following set of pre-defined validation rules. required - mandatory field validation. Has no variables.

<field property="name" depends="required">
        <arg0 key="customer.name"/>
    </field>
requiredif - field dependant validator Deprecated, use validwhen. validwhen - validator for checking one field against another. see later section titled Designing "Complex Validations with validwhen". minlength - validate input data isn't less than a specified minimum length. Requires a minlength variable.
<field property="name" depends="required,minlength">
        <arg0 key="customer.name"/>
        <arg1 name="minlength" key="${var:minlength}" resource="false"/>
        <var><var-name>minlength</var-name><var-value>3</var-value></var>
    </field>
maxlength - validate input data doesn't exceed a specified maximum length. Requires a maxlength variable.
<field property="name" depends="required,maxlength">
        <arg0 key="customer.name"/>
        <arg1 name="maxlength" key="${var:maxlength}" resource="false"/>
        <var><var-name>maxlength</var-name><var-value>30</var-value></var>
    </field>
mask - validate format according to a regular expression. Requires a mask variable to specify the regular expression. Since version 1.1, the regular expression must start with a ^ and end with a $ (see example below).
<field property="name" depends="required,mask">
        <msg name="mask" key="registrationForm.lastname.maskmsg"/>
        <arg0 key="registration.name"/>
        <var><var-name>mask</var-name><var-value>^[a-zA-Z]*$</var-value></var>
    </field>
byte - validates that a field can be converted to a Byte.
<field property="age" depends="byte">
        <arg0 key="employee.age"/>
    </field>
short - validates that a field can be converted to a Short.
<field property="productnumber" depends="short">
        <arg0 key="order.prodno"/>
    </field>
integer - validates that a field can be converted to an Integer.
<field property="ordernumber" depends="integer">
        <arg0 key="order.number"/>
    </field>
long - validates that a field can be converted to a Long.
<field property="ordernumber" depends="long">
        <arg0 key="order.number"/>
    </field>
float - validates that a field can be converted to a Float.
<field property="amount" depends="float">
        <arg0 key="sale.amount"/>
    </field>
double - validates that a field can be converted to a Double.
<field property="amount" depends="double">
        <arg0 key="sale.amount"/>
    </field>
date - validates that a field can be converted to a Date. This validation rule uses java.text.SimpleDateFormat to parse the date and optionally either a datePattern or datePatternStrict variable can be used. If no pattern is specified the default short date format is assumed. The difference between using the datePatternStrict and datePattern variables is that datePatternStrict checks additionally that the input data is the same length as the pattern specified (so for example 1/1/2004 would fail with a pattern of MM/dd/yyyy).
<field property="saledate" depends="required,date">
        <arg0 key="myForm.saledate"/>
        <var><var-name>datePattern</var-name><var-value>MM/dd/yyyy</var-value></var>
    </field>
    

    <field property="saledate" depends="required,date">
        <arg0 key="sale.orderdate"/>
        <var><var-name>datePatternStrict</var-name><var-value>MM/dd/yyyy</var-value></var>
    </field>
range - validate number range. Deprecated, use intRange, floatRange or doubleRange. intRange - validates that an integer field is within a specified range. Requires min and max variables to specify the range. This validator depends on the integer validator which must also be in the field's depends attribute.
<field property="age" depends="required,integer,intRange">
        <arg0 key="employee.age"/>
        <arg1 name="intRange" key="${var:min}" resource="false"/>
        <arg2 name="intRange" key="${var:max}" resource="false"/>
        <var><var-name>min</var-name><var-value>18</var-value></var>
        <var><var-name>max</var-name><var-value>65</var-value></var>
    </field>
floatRange - validates that a float field is within a specified range Requires min and max variables to specify the range. This validator depends on the float validator which must also be in the field's depends attribute.
<field property="ordervalue" depends="required,float,floatRange">
        <arg0 key="order.value"/>
        <arg1 name="floatRange" key="${var:min}" resource="false"/>
        <arg2 name="floatRange" key="${var:max}" resource="false"/>
        <var><var-name>min</var-name><var-value>100</var-value></var>
        <var><var-name>max</var-name><var-value>4.99</var-value></var>
    </field>
doubleRange - validates that a double field is within a specified range Requires min and max variables to specify the range. This validator depends on the double validator which must also be in the field's depends attribute.
<field property="ordervalue" depends="required,double,doubleRange">
        <arg0 key="employee.age"/>
        <arg1 name="doubleRange" key="${var:min}" resource="false"/>
        <arg2 name="doubleRange" key="${var:max}" resource="false"/>
        <var><var-name>min</var-name><var-value>100</var-value></var>
        <var><var-name>max</var-name><var-value>4.99</var-value></var>
    </field>
creditCard - validate credit card number format
<field property="name" depends="required, creditCard">
        <arg0 key="customer.cardnumber"/>
    </field>
email - validate email address format
<field property="customeremail" depends="email">
        <arg0 key="customer.email"/>
    </field>

Manually validating a form

NOTE: for manual validation to work as illustrated here, you should either not use custom forms, or have your custom forms to extend DefaultForm. Manual validation is very simple. If you’re using external states, you simply call myStateForm.validate(ControllerRequest request) in your handle state, and the method will return an ErrorCollection with the failed validation messages (or empty if the form passed all the validations):

public class MyHandleState
    extends State {

  public MyHandleState() {
    super();
  }

  public MyHandleState(String newName, String newDescrip) {
    super(newName, newDescrip);
  }

  public void perform(StateForm stateForm, ControllerRequest params,
                      ControllerResponse response) throws
      NonHandleableException, ControllerException {

    ErrorCollection errors = stateForm.validate(params);

    if (errors.getErrorCount() != 0) {
      // handle an invalid form
      // in this case go back to the prompt state
      response.saveErrors(errors);
      try {
        response.setFormCache();
        transition("myPromptState", params, response);
      }
      catch (NonHandleableException nhe) {
        errors.addError("problem after transition");
      }
    }
    else {
      // handle a valid form
      // for example update a DBObject with the form data
    }
  }
If you’re using internal states, it’s a bit trickier, since internal states are not aware of ActionForms.
&mldr;
protected void runMyHandleState(ControllerRequest params, ControllerResponse response){
&mldr;
//cast your request to a form-aware request
ServletControllerRequest cparams = (ServletControllerRequest)params;
//retrieve the form from the request&mldr;
DefaultForm myForm = (DefaultForm)cparams.getForm();
&mldr;
//the rest of the process is exactly as in the external states
}   response.saveErrors(errors);

  setResponse(response);

  return;

}

Automatically validating a form

Automatic form validation is configured in the action mappings of your app’s struts-config.xml, and will be enabled or disabled for all the states in the controller referenced by the mapping. To enable it, you simply set the validate=”true” property for the action, and that’s it :D

<struts-config>
<action path="/myAction" type="com.mycompany.myapp.controller.MyController" name="default" scope="request" validate="true">
<forward name="whatever" path="/pages/whatever.jsp"/>
</action>
</action-mappings>
</struts-config>
I repeat, that’s it.. Expresso will handle the rest for you

Using client-side Javascript validation

Struts Validator can automatically generate Javascript code for validating your forms at the client-side (server-side validation will also be performed no matter if client-side validation is enabled or not). For using it, there are two steps to do in your JSP. 1)load the Javascript code corresponding to your form

<html:javascript formName=&rdquo;myHandleState&rdquo; />
2)tell the form to call the JS code on submit
<html:form action="/myAction" method="POST" onsubmit="return validateMyHandleState(this)">
Now you’ll form will be validated following the rules you defined in validation.xml both, client-side and server-side

Writing your own pluggable validators

Please refer to the Struts Validator Developer guide. I couldn’t explain better how to do this… http://struts.apache.org/userGuide/dev_validator.html

Conclusion

The Validator integration in Expresso gives us an unmatched power and flexibility for validating user input. It also brings less painful the port from Struts applications where validation rules already exist.

As this feature will be adopted by the community, new plugins and other improvements will help making this tool even more powerful.

Contributors

The following persons have contributed their time to this chapter:

Note

Was this EDG documentation helpful? Do you wish to express your appreciation for the time expended over years developing the EDG doc? We now accept and appreciate monetary donations. Your support will keep the EDG doc alive and current. Please click the Donate button and enter ANY amount you think the EDG doc is worth. In appreciation of a $35+ donation, we'll give you a subscription service by emailing you notifications of doc updates; and donations $75+ will also receive an Expresso T-shirt. All online donation forms are SSL secured and payment can be made via Credit Card or your Paypal account. Thank you in advance.

Copyright © 2001-2004 Jcorporate Ltd. All rights reserved.