| <?xml version="1.0" encoding="UTF-8"?> |
| <!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.0//EN" "../../dtd/document-v10.dtd"> |
| |
| <document> |
| <header> |
| <title>Using Form Validation</title> |
| <version>0.2</version> |
| <type>Overview document</type> |
| <authors> |
| <person name="Christian Haul" email="haul@apache.org"/> |
| </authors> |
| </header> |
| <body> |
| <s1 title="Introduction"> |
| |
| <p> |
| For most web applications input is essential. Apache Cocoon provides a |
| variety of modules to support basic interaction like simple syntax checking |
| of input data or writing input data to databases. |
| </p> |
| |
| <p> |
| Two different packages deal with validating user input:<link |
| href="../../howto/xmlform-wizard/howto-xmlform-wizard.html">XMLForm</link> |
| which tries to stay as close as possible with the <link |
| href="http://www.w3.org">W3C</link> <link |
| href="http://www.w3.org/MarkUp/Forms/">XForms</link> working draft. |
| Another, simpler and older implementation is the validation using the |
| <code>FormValidatorAction</code>, which is described here. |
| </p> |
| |
| <p> |
| To validate user input, an action, the <code>FormValidatorAction</code>, is |
| placed in your pipeline. Together with a descriptor file, that specifies |
| the allowed input, this action validates the request parameters. Based on |
| the result, a different page can be displayed and feedback can be given to |
| the user either using XSP and the <code>formval</code> logicsheet or the |
| <code>SimpleFormTransformer</code>. |
| </p> |
| |
| <s2 title="Sitemap Usage"> |
| <p> |
| To take advantage of the form validator action, create two pages. One for |
| the input form and one indicating the acceptance of the reservation. |
| Create a pipeline in your sitemap so that the confirmation page is only |
| shown when the action completed successfully and the input form is |
| returned otherwise. |
| </p> |
| |
| <source> |
| <![CDATA[ |
| <?xml version="1.0"?> |
| <map:match pattern="car-reservation"> |
| <map:act type="form-validator"> |
| <!-- add you favourite database action here --> |
| <map:parameter name="descriptor" value="descriptor.xml"/> |
| <map:parameter name="validate-set" value="car-reservation"/> |
| <map:generate type="serverpages" src="OK.xsp"/> |
| <map:transform src="stylesheets/dynamic-page2html.xsl"/> |
| <map:serialize/> |
| </map:act> |
| <map:generate type="serverpages" src="test/ERROR.xsp"/> |
| <map:transform src="stylesheets/dynamic-page2html.xsl"/> |
| <map:serialize/> |
| </map:match> |
| ]]> |
| </source> |
| |
| <p> |
| Note here that you may not use a redirection to point to the pages if you |
| would like to access the validation results e.g. on the error page. A |
| redirection would create a new request object and thus discard the |
| validation results. |
| </p> |
| |
| <p> |
| A different example, that does not need serverpages but the |
| <code>SimpleFormTransformer</code>: |
| </p> |
| |
| <source> |
| <![CDATA[ |
| <?xml version="1.0"?> |
| <map:match pattern="car-reservation"> |
| <map:act type="req-params"> |
| <map:parameter name="parameters" value="order"/> |
| |
| <map:act type="form-validator"> |
| <map:parameter name="descriptor" value="descriptor.xml"/> |
| <map:parameter name="validate-set" value="car-reservation"/> |
| <!-- add you favourite database action here --> |
| |
| <map:generate type="file" src="OK.xml"/> |
| <map:transform src="stylesheets/dynamic-page2html.xsl"/> |
| <map:serialize/> |
| </map:act> |
| </map:act> |
| <map:generate type="file" src="test/ERROR.xml"/> |
| <map:transform src="stylesheets/dynamic-page2html.xsl"/> |
| <map:transform type="simple-form"/> |
| <map:serialize/> |
| </map:match> |
| ]]> |
| </source> |
| |
| <p> |
| Although this looks more complicated at first, it has advantages if you |
| don't want to or cannot use XSP. For example, if the form is stored as |
| XHTML in a database, XSP could not be used to fill the form with values |
| from request parameters or to display detailed error messages. |
| </p> |
| <note> |
| Keep in mind that files, here the descriptor file, could be specified |
| using the <code>cocoon:</code> pseudo-protocol. Thus the file could be |
| generated dynamically from another pipeline! |
| </note> |
| |
| </s2> |
| |
| <s2 title="The Descriptor File"> |
| |
| <p> |
| For details on the syntax of the descriptor file see javadocs. Basically |
| it consists of two sections, a list of parameters and their properties and |
| a list of constraints or constraint sets. The file syntax is set up so |
| that it can be shared with the database actions. |
| </p> |
| |
| <s3 title="The types recognized by validator and their attributes"/> |
| <table> |
| <tr> |
| <td><strong>string</strong></td><td>nullable="yes|no" default="str"</td> |
| </tr> |
| <tr> |
| <td><strong>long</strong></td><td>nullable="yes|no" default="123123"</td> |
| </tr> |
| <tr> |
| <td><strong>double</strong></td><td>nullable="yes|no" default="0.5"</td> |
| </tr> |
| </table> |
| |
| <p> |
| Default value takes place only when specified parameter is nullable and |
| really is null or empty. Long numbers may be specified in decimal, hex or |
| octal values as accepted by java.Lang.decode (String s). |
| </p> |
| |
| <s3 title="Constraints"/> |
| <table> |
| <tr> |
| <td>matches-regex</td><td>POSIX regular expression</td> |
| </tr> |
| <tr> |
| <td>one-of</td><td>List of strings, enclosed and separated by <code>|</code></td> |
| </tr> |
| <tr> |
| <td>min-len</td><td>positive integer</td> |
| </tr> |
| <tr> |
| <td>max-len</td><td>positive integer</td> |
| </tr> |
| <tr> |
| <td>min</td><td>Double / Long</td> |
| </tr> |
| <tr> |
| <td>max</td><td>Double / Long</td> |
| </tr> |
| </table> |
| <p> |
| Constraints can be defined globally for a parameter and can be overridden |
| by redefinition in a constraint-set. Thus if e.g. a database field can take |
| at maximum 200 character, this property can be set globally. |
| </p> |
| <p> |
| Values in parameter arrays are validated individually and the worst |
| error is reported back. |
| </p> |
| |
| <source> |
| <![CDATA[ |
| <?xml version="1.0"?> |
| <root> |
| |
| <parameter name="persons" type="long" min="1" default="4" nullable="no"/> |
| <parameter name="deposit" type="double" min="10.0" max="999.99"/> |
| <parameter name="email" type="string" max-len="50" |
| matches-regex="^[\d\w][\d\w\-_\.]*@([\d\w\-_]+\.)\w\w\w?$"/> |
| <parameter name="colour" type="string" one-of="|red|green|blue|white|"/> |
| |
| <constraint-set name="car-reservation"> |
| <validate name="persons"/> |
| <validate name="deposit" min="50.0"/> |
| <validate name="email"/> |
| </constraint-set> |
| |
| </root> |
| ]]> |
| </source> |
| |
| <p> |
| The above could for example describe expected input from a reservation |
| form. Specifications in a constraint set take precedence over the general |
| ones. |
| </p> |
| |
| </s2> |
| |
| |
| <s2 title="XSP Usage"> |
| |
| <p> |
| To give the user some feedback why her/his submitted data was rejected |
| there is a special taglib "xsp-formval". Declare its name space as usual. |
| </p> |
| |
| <p> |
| If only interested in validation results, just: |
| </p> |
| |
| <source> |
| <![CDATA[ |
| <xsp-formval:on-ok name="persons"> |
| <myapp:error>(ERROR)</myapp:error> |
| </xsp-formval:on-ok> |
| ]]> |
| </source> |
| |
| <p> |
| Alternatively, if you just want a boolean value from the logicsheet if a |
| test is successful, use this method: |
| </p> |
| |
| <source> |
| <![CDATA[ |
| <xsp:logic> |
| if (!<xsp-formval:is-ok name="persons"/>) { |
| <myapp:error>(ERROR)</myapp:error> |
| }; |
| </xsp:logic> |
| ]]> |
| </source> |
| |
| <p> |
| Internationalization issues are a separate concern and are not discussed |
| here. |
| </p> |
| <p> |
| Currently the following validation result codes are supported: |
| </p> |
| |
| <table> |
| <tr><th>tag</th><th>Meaning</th></tr> |
| <tr><td>xsp-formval:is-ok</td><td>no error occurred, parameter |
| successfully checked</td></tr> |
| <tr><td>xsp-formval:is-error</td><td>some error occurred, this is a result |
| that is never set but serves as a comparison target |
| </td></tr> |
| <tr><td>xsp-formval:is-null</td><td>the parameter is null but |
| isn't allowed to</td></tr> |
| <tr><td>xsp-formval:is-toosmall</td><td>either value or length in case of |
| a string is less than the specified minimum</td></tr> |
| <tr><td>xsp-formval:is-toolarge</td><td>either value or length in case of |
| a string is greater than the specified maximum</td></tr> |
| <tr><td>xsp-formval:is-nomatch</td><td>a string parameter's value is not |
| matched by the specified regular expression</td></tr> |
| <tr><td>xsp-formval:is-notpresent</td><td>this is returned when the result |
| of a validation is requested but no such result is found in the request |
| attribute </td></tr> |
| </table> |
| |
| <p> |
| For debugging purposes or if you would like to iterate over the validation |
| results, <code>xsp-formval:results</code> returns a |
| <code>java.util.Map</code> containing them all. |
| </p> |
| |
| <p> |
| If you would like to be more specific what went wrong, you can query the |
| descriptor file for attributes. |
| </p> |
| |
| <p> |
| First set the url of the file or resource that contains the parameter |
| descriptions and constraint sets. This needs to be an ancestor to all |
| other tags (of this taglib). Multiple use of this tag is allowed (although |
| probably not necessary). |
| </p> |
| |
| <p> You need to do this only if you plan to query the descriptor file or if |
| you'd like to use the shorthand below. |
| </p> |
| |
| <source> |
| <![CDATA[ |
| <xsp-formval:descriptor name="descriptor.xml" constraint-set="reservation"> |
| deposit must be at least EUR |
| <xsp-formval:get-attribute parameter="deposit" name="min"/> |
| </xsp-formval:descriptor> |
| ]]> |
| </source> |
| |
| <p> |
| If you need to use one parameter a lot, there's a short hand. Use this |
| e.g. if you'd like to set up the properties of an input tag according to |
| the information from the descriptor file or if you'd like to give detailed |
| error messages. |
| </p> |
| |
| <p> |
| Note that you can specify additional attributes in the description file |
| that are not understood (and therefore ignored) by the FormValidatorAction |
| but that could be queried here. This might be e.g. the size of the input |
| field which might be different from the max-len a parameter can take. |
| </p> |
| |
| <source> |
| <![CDATA[ |
| <xsp-formval:descriptor name="descriptor.xml" constraint-set="car-reservation"> |
| <xsp-formval:validate name="deposit"> |
| <xsp:logic> |
| if (<xsp-formval:is-null/>) { |
| <myapp:error> (you must specify a deposit)) </myapp:error> |
| } else if ( <xsp-formval:is-toosmall/> ) { |
| <myapp:error> |
| (deposit is too small (< <xsp-formval:get-attribute name="min"/>)) |
| </myapp:error> |
| } else if ( <xsp-formval:is-toolarge/> ) { |
| <myapp:error> |
| (deposit is too large (> <xsp-formval:get-attribute name="max"/>)) |
| </myapp:error> |
| } else { |
| <myapp:error> (ERROR) </myapp:error> |
| }; |
| </xsp:logic> |
| </xsp-formval:validate> |
| </xsp-formval:descriptor> |
| ]]> |
| </source> |
| |
| </s2> |
| |
| <s2 title="SimpleFormTransformer"> |
| |
| <p> |
| An alternative solution to using the <code>formval</code> logicsheet and |
| XSP is to use the <code>SimpleFormTransformer</code>. If fills the form |
| with values obtained from request parameters, overwriting existing |
| values. Hence the data entered by the user is not discarded when it does |
| not validate successfully. |
| </p> |
| |
| <note> |
| Beware when using the <code>SimpleFormTransformer</code> together with |
| XSP: The observer behaviour can be very confusing when trying to set a |
| value from XSP and it is silently overwritten by the transformer! |
| </note> |
| |
| <p> |
| When a form element carries the attribute <code>fixed="true"</code>, the |
| transformer does not replace the value. |
| </p> |
| |
| <p> |
| Feedback can be given to the user through <code><error/></code> |
| tags. Error tags need to have a name attribute identical to the input |
| element they refer to. Multiple error elements may be present for any |
| input element. The <code>FormValidatorAction</code> sets a special field |
| <code>*</code> that indicates whether all parameters were validated |
| successfully or not. |
| </p> |
| |
| <p> |
| An error element is omitted together with all contents whenever the |
| specified condition is not met. Conditions are either exact or greater |
| equal constraints indicated by the attribute <code>when</code> or |
| <code>when-ge</code> respectively. |
| </p> |
| |
| <p> |
| Allowed values for error conditions are: <code>ok, not-present, error, |
| is-null, too-small, too-large, no-match </code> |
| </p> |
| |
| <source> |
| <![CDATA[ |
| <input name="email" type="text"/><error name="email" when-ge="error">*</error> |
| <!-- ... --> |
| <error name="email" when="is-null">Please enter your email address.</errro> |
| <error name="email" when="no-match">Please enter a <em>syntacticly</em> correct |
| email address.</errro> |
| ]]> |
| </source> |
| </s2> |
| |
| <s2 title="Other Validations"> |
| |
| <p> |
| In addition to validating form input, other actions exists that validate |
| values from different sources using the same techniques and syntax. For |
| example, the <code>SessionValidatorAction</code> operates on session |
| attributes. |
| </p> |
| |
| </s2> |
| |
| </s1> |
| |
| </body> |
| </document> |
| |