[cvs] expresso/expresso-web/expresso/doc/edg validation.xml
JCorporate Ltd
jcorp at jcorp2.servlets.net
Mon Aug 9 09:30:29 PDT 2004
Update of /home/javacorp/.cvs/expresso/expresso/expresso-web/expresso/doc/edg
In directory jcorp2.servlets.net:/tmp/cvs-serv16617
Added Files:
validation.xml
Log Message:
validator chapter for EDG
--- NEW FILE: validation.xml ---
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="validation" xreflabel="Validating user input">
<title>Validating user input</title>
<para><note>
<para>If you find this EDG documentation helpful please consider <link
linkend="donate_validation">DONATING</link>! to keep the doc alive and
current.</para>
</note></para>
<para><informaltable colsep="0" frame="none" pgwide="1" rowsep="0">
<tgroup cols="2" colsep="0" rowsep="0">
<colspec align="left" colsep="0" colwidth="50%" rowsep="0" />
<colspec align="right" colsep="0" colwidth="50%" rowsep="0" />
<tbody>
<row>
<entry><emphasis role="bold">Version:</emphasis> <emphasis
role="version">Expresso 5.6</emphasis></entry>
<entry><emphasis role="bold">Maintainer:</emphasis><ulink
url="mailto:r.davidovich at dmci.eu.com?Subject=EDG"><emphasis
role="maintainer">Raul Davidovich</emphasis></ulink></entry>
</row>
</tbody>
</tgroup>
</informaltable></para>
<para>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.</para>
<sect1 id="validatorSetUp">
<title>Setting up the Validator plugin</title>
<para>To set up the plugin, one must add it to the struts-config.xml file,
as follows: <programlisting> <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></programlisting> 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: <programlisting> <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></programlisting> 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:<itemizedlist>
<listitem>
<para><argn> tags defining replacement parameters for any
messages returned to the user. N is the order of the message to
replace.</para>
</listitem>
<listitem>
<para><var> tags with variable properties to pass to the
validation functions (the maximum length of the field, a mask to
apply, etc)</para>
</listitem>
<listitem>
<para><msg> tags specifying custom message keys for
validators</para>
</listitem>
</itemizedlist> <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: <programlisting> <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></programlisting> 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: <programlisting> <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></programlisting></para>
</sect1>
<sect1 id="builtInValidators">
<title>Standard Built In Validations</title>
<indexterm>
<primary>Validator</primary>
<secondary>Built In</secondary>
</indexterm>
<para>Validator is shipped with the following set of pre-defined
validation rules. required - mandatory field validation. Has no variables.
<programlisting> <field property="name" depends="required">
<arg0 key="customer.name"/>
</field></programlisting> 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. <programlisting> <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></programlisting> maxlength - validate input data doesn't
exceed a specified maximum length. Requires a maxlength variable.
<programlisting> <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></programlisting> 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). <programlisting> <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></programlisting> byte - validates that a field can be
converted to a Byte. <programlisting> <field property="age" depends="byte">
<arg0 key="employee.age"/>
</field></programlisting> short - validates that a field can be
converted to a Short. <programlisting> <field property="productnumber" depends="short">
<arg0 key="order.prodno"/>
</field></programlisting> integer - validates that a field can be
converted to an Integer. <programlisting> <field property="ordernumber" depends="integer">
<arg0 key="order.number"/>
</field></programlisting> long - validates that a field can be
converted to a Long. <programlisting> <field property="ordernumber" depends="long">
<arg0 key="order.number"/>
</field></programlisting> float - validates that a field can be
converted to a Float. <programlisting> <field property="amount" depends="float">
<arg0 key="sale.amount"/>
</field></programlisting> double - validates that a field can be
converted to a Double. <programlisting> <field property="amount" depends="double">
<arg0 key="sale.amount"/>
</field></programlisting> 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). <programlisting> <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></programlisting> 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. <programlisting> <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></programlisting> 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. <programlisting> <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></programlisting> 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. <programlisting> <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></programlisting> creditCard - validate credit card number
format <programlisting> <field property="name" depends="required, creditCard">
<arg0 key="customer.cardnumber"/>
</field></programlisting> email - validate email address format
<programlisting> <field property="customeremail" depends="email">
<arg0 key="customer.email"/>
</field></programlisting> url - validates url format. Has four
optional variables (allowallschemes, allow2slashes, nofragments and
schemes) which can be used to configure this validator. allowallschemes
specifies whether all schemes are allowed. Valid values are true or false
(default is false). If this is set to true then the schemes variable is
ignored. allow2slashes specifies whether double '/' characters are
allowed. Valid values are true or false (default is false). nofragments
specifies whether fragements are allowed. Valid values are true or false
(default is false - i.e. fragments are allowed). schemes - use to specify
a comma separated list of valid schemes. If not specified then the
defaults are used which are http, https and ftp. <programlisting> <field property="custUrl" depends="url">
<arg0 key="customer.url"/>
</field>
<field property="custUrl" depends="url">
<arg0 key="customer.url"/>
<var>
<var-name>nofragments</var-name>
<var-value>true</var-value>
</var>
<var>
<var-name>schemes</var-name>
<var-value>http,https,telnet,file</var-value>
</var>
</field></programlisting> </para>
</sect1>
<sect1 id="defineableAndDBMaint">
<title>Manually validating a form</title>
<para><emphasis>NOTE: for manual validation to work as illustrated here,
you should either not use custom forms, or have your custom forms to
extend DefaultForm. </emphasis> 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):
<programlisting>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
}
}
</programlisting> If youâre using internal states, itâs a bit trickier, since
internal states are not aware of ActionForms. <programlisting>â¦
protected void runMyHandleState(ControllerRequest params, ControllerResponse response){
â¦
//cast your request to a form-aware request
ServletControllerRequest cparams = (ServletControllerRequest)params;
//retrieve the form from the requestâ¦
DefaultForm myForm = (DefaultForm)cparams.getForm();
â¦
//the rest of the process is exactly as in the external states
} response.saveErrors(errors);
setResponse(response);
return;
}</programlisting></para>
</sect1>
<sect1>
<title>Automatically validating a form</title>
<para>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
<programlisting><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></programlisting> <emphasis>I repeat, thatâs it..
Expresso will handle the rest for you</emphasis></para>
</sect1>
<sect1>
<title>Using client-side Javascript validation</title>
<para>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 <programlisting><html:javascript formName=âmyHandleStateâ /></programlisting>
2)tell the form to call the JS code on submit <programlisting><html:form action="/myAction" method="POST" onsubmit="return validateMyHandleState(this)"></programlisting>
Now youâll form will be validated following the rules you defined in
validation.xml both, client-side and server-side</para>
</sect1>
<sect1>
<title>Designing Complex Validations with valid when</title>
<para>[Since Struts 1.2.0] A frequent requirement in validation design is
to validate one field against another (for example, if you have asked the
user to type in a password twice for confirmation, to make sure that the
values match.) In addition, there are fields in a form that may only be
required if other fields have certain values. The validwhen validation
rule is designed to handle these cases. The validwhen rule takes a single
var field, called test. The value of this var is a boolean expression
which must be true in order for the validation to success. The values
which are allowed in the expression are:<itemizedlist>
<listitem>
<para>Single or double-quoted string literals. </para>
</listitem>
<listitem>
<para>Integer literals in decimal, hex or octal format </para>
</listitem>
<listitem>
<para>The value null which will match against either null or an
empty string </para>
</listitem>
<listitem>
<para>Other fields in the form referenced by field name, such as
customerAge</para>
</listitem>
<listitem>
<para>Indexed fields in the form referenced by an explicit integer,
such as childLastName[2] </para>
</listitem>
<listitem>
<para>Indexed fields in the form referenced by an implicit integer,
such as childLastName[], which will use the same index into the
array as the index of the field being tested. </para>
</listitem>
<listitem>
<para>Properties of an indexed fields in the form referenced by an
explicit or implicit integer, such as child[].lastName, which will
use the same index into the array as the index of the field being
tested. </para>
</listitem>
<listitem>
<para>The literal *this, which contains the value of the field
currently being tested</para>
</listitem>
</itemizedlist></para>
<para>As an example of how this would work, consider a form with fields
sendNewsletter and emailAddress. The emailAddress field is only required
if the sendNewsletter field is not null. You could code this using the
validwhen rule as: <programlisting> <field depends="validwhen" property="emailAddress">
<arg0 key="userinfo.emailAddress.label" />
<var>
<var-name>test</var-name>
<var-value>((sendNewsletter == null) or (*this* != null))</var-value>
</var>
</field></programlisting>Which reads as: this field is valid if
sendNewsletter is null or the field value is not null. </para>
<para></para>
<para>Here's a slightly more complicated example using indexed fields.
Assume a form with a number of lines to allow the user to enter part
numbers and quantities they wish to order. An array of beans of class
orderLine is used to hold the entries in a property called orderLines. If
you wished to verify that every line with part number also had a quantity
entered, you could do it with:<programlisting> <field depends="validwhen" indexedListProperty="orderLines" property="quantity">
<arg0 key="orderform.quantity.label" />
<var>
<var-name>test</var-name>
<var-value>((orderLines[].partNumber == null) or (*this* != null))</var-value>
</var>
</field></programlisting>Which reads as: This field is value if the
corresponding partNumber field is null, or this field is not null. </para>
<para> As a final example, imagine a form where the user must enter their
height in inches, and if they are under 60 inches in height, it is an
error to have checked off nbaPointGuard as a career. <programlisting> <field depends="validwhen" property="nbaPointGuard">
<arg0 key="careers.nbaPointGuard.label" />
<var>
<var-name>test</var-name>
<var-value>((heightInInches &gt;= 60) or (*this* == null))</var-value>
</var>
</field></programlisting> <emphasis>A few quick notes on the grammer.
All comparisons must be enclosed in parens. Only two items may be joined
with and or or If both items to be compared are convertable to ints, a
numeric comparison is done, otherwise a string comparison is done.
</emphasis></para>
</sect1>
<sect1>
<title>Writing your own pluggable validators</title>
<para>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</para>
</sect1>
<sect1>
<title>Conclusion</title>
<para>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.</para>
<para>As this feature will be adopted by the community, new plugins and
other improvements will help making this tool even more powerful.</para>
<sect2><title>Contributors</title> <para> The following persons have
contributed their time to this chapter: <itemizedlist mark="bullet">
<listitem> <para> Raul Davidovich <link linkend="jgroup">(JGroup
Expert)</link> </para> </listitem> </itemizedlist> </para></sect2>
<para><note> <para id="donate_dbmaint"> 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. </para> <para> <ulink
url="http://www.jcorporate.com/edgdoc.html"> <inlinemediaobject>
<imageobject> <imagedata fileref="../images/edg/paypal.bmp"
format="BMP"></imagedata> </imageobject> </inlinemediaobject> </ulink>
</para> </note></para>
<para>Copyright © 2001-2004 Jcorporate Ltd. All rights reserved.</para>
</sect1>
</chapter>
More information about the cvs
mailing list