Print Header

Related Topics

Related Case Studies

Contact Blue Fish

Blue Fish Development Group
701 Brazos St. #700
Austin, TX 78701
(512) 469-9300

Validation in WDK

October 1, 2004 - Article by Rex Staples

Learn how to integrate custom validation controls into Documentum WDK applications.

Introduction to Validation

Validation of form fields is an important part of any user interface. Validation can prevent users from entering incorrect or malformed data, enforce required fields, thwart potential buffer overflows, or perform more complicated checks to guarantee the data is well-formed before it is used in an operation.

WDK 5 Validation Framework

Because almost all forms require validation time is often wasted by hand-coding validation into each application. Fortunately, form validation can be generalized and re-applied as needed. WDK 5 introduced a validation framework that provides declarative support for typical user validation tasks, is extensible through “plug-in” validation, and offers data dictionary integration.

In the WDK 5 validation framework, a validator is a control that checks one or more input controls for a specific type of error condition and displays a description of the problem if an error is found. It is common for more than one validator control to be used against each input control.

Disabling Validation

If validation is turned on it will be initiated in the form processor prior to a server-side action event being handled. Validation is on by default; however, it may be disabled by setting the <dmf:webform> element’s validation attribute to false. Disabling validation may be necessary if it is slowing down the UI redraw or if you don’t need validation on all events. Even when disabled you may explicitly call the validate() method in your component to run all the validators or write a custom routine to selectively execute one or more validators.

Manual Validation

Manual validation of the controls on the page is still possible using a mixture of javascript and HTML for client-side validation, or Java for server-side validation. Because these specialized one-off validators have limited use and no standardized way of delivering error messages back to the user, using the WDK 5 validation framework is strongly recommended.

Overview of Existing Validators

The WDK validation framework provides ten generic validation controls. Each validator is associated to an input controls and configured by setting the validator’s tag attributes in the JSP page.

The validation tag definitions can be found in the dmform tag library definition (tld), while the Control and ControlTag class for each of these validators can be found in the com.documentum.web.form.control.validator package.

If the value of the control to validate is a null or empty value, the control is assumed to be valid. The exception to this rule is the required field validator. Therefore, it is often useful to combine the required field validator with other validators to ensure a valid value is provided.

The tag attributes below are common for each of the validation control tags (not including the validation summary tag).

Common Validator Tag Attributes

  • name (required) - the name of the validation control
  • controltovalidate (required) - the name of the input control to be validated
  • enabled - the validator is enabled by default, but set this attribute to false to disable the validator, or true to explicity enable the validator
  • nlsid - the nlsid of the internationalized error message to display if the control to validate does not pass validation
  • errormessage - the error message to display if the control to validate does not pass validation; the nlsid attribute takes precedence over this attribute
  • visible - by default the validator will display an error message when validation fails; set this attribute to false to prevent the validator from outputting an error message (useful if using the validationsummary tag)
  • style - the (css) style properties for the validator error message
  • cssclass - the css class to apply to the validator error message
  • id - this attribute is not used

Compare Validator

The compare validator verifies that the input control value passes evaluation with the specified operator and comparison value. The comparison value may either be the value specified by the comparevalue attribute or the value of the input control identified by the comparecontrol attribute.

Example

                                <dmf:password name="password" size="10"/>
<dmf:password name="password_confirm" size="10"/>

<dmf:comparevalidator
   name="val_compare_password"
   controltovalidate="password"
   comparecontrol="password_confirm"
   errormessage="The passwords do not match."
   type="string"
   operator="equal"/>

                            

Tag Attributes

  • type - determines the way the fields are compared; valid values are string (default) and integer
  • operator - the condition to apply to the control to validate value and the comparison value; valid values are equal (default), notequal, greaterthan, greaterthanequal, lessthan, and lessthanequal
  • comparevalue - the value which is compared to the value of the control to validate
  • comparecontrol - the input control whose value is compared to the value of the control to validate

Date Validator

The date validator is used to validate a dmf:dateinput control. The validation will not pass unless the submitted value is a valid date.

Example

                                <dmf:dateinput name="birthday"/>

<dmf:datevalidator
   name="val_date_birthday"
   controltovalidate="birthday"
   errormessage="Bad date entered."/>

                            

Date Time Validator

The date time validator is used to validate a dmf:datetime control. The validation will not pass unless the submitted value is a valid date and time.

Example

                                <dmf:datetime name="appointment"/>

<dmf:datetimevalidator
   name="val_datetime_appointment"
   controltovalidate="appointment"
   errormessage="Bad date/time.."/>

                            

Input Mask Validator

The input mask validator verifies that the value of the control to validate matches a pattern of characters. This validator is similar to the regular expression validator; however, a much simpler pattern may be used (same as Content Server masks).

Example

                                <dmf:text name="ssn" size="12"/>

<dmf:inputmaskvalidator
   name="val_mask_ssn"
   controltovalidate="ssn"
   errormessage="Must be in the format nnn-nnn-nnnn."
   inputmask="###-###-####"/>

                            

Tag Attributes

  • inputmask - the pattern to test against

The inputmask attribute accepts a string of characters with the notations below. To escape a masked character for use as a literal member of the mask string, use a double backslash (\\) before the character.

Mask Notation

  • # - numeric characters
  • & - all characters
  • A - alphanumeric characters only
  • ? - alphabetic characters only
  • U - uppercase alphabetic characters only
  • L - lowercase alphabetic characters only

Multi-values Input Mask Validator

The multi-values input mask validator validates multiple values in a dmf:label control using an input mask and a separator character. See the mask notation in the input mask validator for valid characters to use in the inputmask attribute.

Example

                                <dmf:label name="zipcodes" label="<%= zipcodes.join(",") %>" />

<dmf:multivaluesinputmaskvalidator
   name="val_multivaluesmask_zipcodes"
   controltovalidate="zipcodes"
   errormessage="One or more zipcodes are invalid."
   inputmask="#####"
   separator=","/>

                            

Tag Attributes

  • inputmask- the pattern to test against
  • separator - the character used to delimit the input values

Multi-values Required Field Validator

The multi-values required field validator validates that all of the required values in a dmf:listbox control have been set.

Example

                                <dmf:datalistbox name='types' size='5'
    query="select r_object_id, name from dm_type">
  <dmf:dataoptionlist>
    <dmf:option datafield="r_object_id" labeldatafield="name"/>
  </dmf:dataoptionlist>
</dmf:datalistbox>

<dmf:multivaluesrequiredfieldvalidator
   name="val_multivaluesrequired_types"
   controltovalidate="datalistbox_click"
   errormessage="One or more options in the list are invalid."
   indicatorstyle="color:red;
   indicator="*" />

                            

Tag Attributes

  • indicator - the string which represents a required field
  • indicatornlsid - the nlsid of the internationalized string which represents a required field
  • indicatorstyle - the (css) style properties for the indicator string
  • indicatorcssclass - the css class to apply to the indicator string

Range Validator

The range validator will test that the value of the control to validate falls within the specified range(s). The upper and lower ranges (both are optional) may either be the value specified by the minvalue and maxvalue attributes or the value of the input controls identified by the minvaluecontrol and maxvaluecontrol attributes.

Example

                                <dmf:text name="quantity" size="1"/>

<dmf:rangevalidator
   name="val_range_quantity"
   controltovalidate="quantity"
   errormessage="Please enter a quantity from 1-5."
   minvalue="1"
   maxvalue="5"/>

                            

Tag Attributes

  • type - determines the way the fields are compared; valid values are string (default, lexicographical range) and integer
  • minvalue - the minimum valid value
  • minvaluecontrol - the control containing the minimum valid value
  • maxvalue - the maximum valid value
  • maxvaluecontrol - the control containing the maximum valid value

Regular Expression Validator

The regular expression validator will test the regex specified by the expression attribute against the value of the control to validate. Regular expression complexity aside, this validator can be tricky to use because the expression applied must encompass the entire value which is being tested.

For example, if the expression is abc and the value tested is aabcc the validator will indicate an error. Should this be a validation error even though a match (in the very middle of the string) can be identified?

It seems as if the supplied expression is being interpreted as ^abc$. The workaround could be to change the expression to .*abc.*, but regular expression veterans will likely be reluctant to use such a heavy-handed technique.

Example

                                <dmf:text name="username" size="40"/>

<dmf:requiredfieldvalidator
   name="val_regexp_username"
   controltovalidate="username"
   errormessage="User names are alphanumeric, with no spaces."
   expression="[a-zA-Z0-9]+”/>

                            

Tag Attributes

  • expression (required) - the regular expression (org.apache.regexp.RE) to apply

Required Field Validator

The required field validator verifies that the input control to validate is not null or empty. Pair this validator with the validators to override their default behavior which passes validation of an input control if a null or empty value is supplied.

Example

                                <dmf:text name="username" size="40"/>

<dmf:requiredfieldvalidator
   name="val_required_username"
   controltovalidate="username"
   errormessage="Username is a required field."
   indicatorstyle="color:red;
   indicator="*" />

                            

Tag Attributes

  • indicator - the string which represents a required field
  • indicatornlsid - the nlsid of the internationalized string which represents a required field
  • indicatorstyle - the (css) style properties for the indicator string
  • indicatorcssclass - the css class to apply to the indicator string

Validation Summary

The validation summary renders an ordered list of messages for failed validators in the form. Although it groups all the error messages in one place it does not suppress the output of the error messages by each of the validators on the page. To do that, you must set the visible attribute of each validation control to false.

This tag does have two drawbacks. First, the messages must be displayed in an ordered list; there is no way to control the layout of the error messages. Second, the markup for the ordered list is present even if there are no errors. The presence of this markup (in the form of <ol> … </ol> tags) leaves whitespace on the page where the error messages would have appeared.

Example

                                <dmf:validationsummary header="Please fix the errors below:"/>
                            

Tag Attributes

  • nlsid - the nlsid of the internationalized error message to display if the control to validate does not pass validation
  • style - the (css) style properties for the validator error message
  • cssclass - the css class to apply to the validator error message
  • id - this attribute is not used
  • header - the text to display above the list of error messages

Client Side Validation

Client-side validation saves time and valuable network resources by validating form fields in the client browser before the form is submitted to the server. The user is immediately alerted to the problematic fields without waiting for a response from the server.

Using a mix of javascript, css, and DHTML each of the above validators could easily include a client-side counterpart. The trick to developing any client-side validator is ensuring cross-browser compatibility. Fortunately, there are many examples of browser-compatible validation code available on the internet.

While client-side validation is not a substitute for server-side validation, it can play an important role in improving the responsiveness of the UI and freeing up precious server resources. In the next section I will include a client-side validation counterpart in the custom validator.

Writing a Custom Validator

The WDK 5.3 dmf:listbox tag implementation adds a multiselect attribute. This attribute allows users to select multiple items from the list. With the ability to select multiple items comes a need to limit users to a maximum number of selected items. Meet the list box select limit validator.

List Box Select Limit Validator

The list box select limit validator restricts the number of selected items in a multiselect list box control. Limit the maximum number of selectable items using the validator’s maxselected attribute.

Two additional attributes are optional. Enable client-side javascript by setting the validateatclient attribute to true. To display a javascript error message each time the user selects too many items set the displayclientalert attribute to true.

By extending com.documentum.web.form.control.validator.BaseValidator and including the common validator tag attributes, the custom validator displays internationalized messages both at the client and the server. BaseValidator extends com.documentum.web.form.control.Label and implements com.documentum.web.form.control.validator.IValidator, the mandatory validator interface.

If enabled, the client-side validator is initialized when the page first loads, and runs each time the list box control’s set of selected items changes. The initialization sets the onchange attribute of the list box control’s select HTML element to a function which keeps the last good set of selected options. If new selection ever exceeds the maximum number selectable options, the selection is invalidated and reverted the to the previous good selection.

The server-side validator implementation fetches from the Request object the array of parameter values for the control to validate. If the array length is larger than the maximum number of values, the validator fails.

Example

                                
<dmf:listbox name="colors" size="7" multiselect="true">
  <dmf:option value="1" label="Red"/>
  <dmf:option value="2" label="Orange"/>
  <dmf:option value="3" label="Yellow"/>
  <dmf:option value="4" label="Green"/>
  <dmf:option value="5" label="Blue"/>
  <dmf:option value="6" label="Indigo"/>
  <dmf:option value="7" label="Violet"/>
</dmf:listbox>

<bfval:listboxselectlimitvalidator
   name="val_limitselection_colors"
   controltovalidate="colors"
   errormessage="You can't select more than three options."/>
   maxselected="3"
   validateatclient="true"
   displayclientalert="true"


                            

Tag Attributes

  • maxselected - the maximum number of items to from the list
  • validateatclient - whether to use javascript to validate the field before the form is posted to the server
  • displayclientalert - if validateatclient is true, this flag toggles whether to alert the user each time they have selected too many items from the list

List Box Select Limit Validator Tag Library Definition

                                
<!--
  - Copyright (c) Blue Fish Development Group 1996-2004. All rights reserved.
  -->

<tag>
  <name>listboxselectlimitvalidator</name>
  <tagclass>com.bluefishgroup.wdk.validator.ListBoxSelectLimitValidatorTag</tagclass>
  <bodycontent>empty</bodycontent>

  <!-- Unique Validator Attributes -->
  <attribute>
     <name>maxselected</name>
     <required>true</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>

  <attribute>
     <name>validateatclient</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>

  <attribute>
     <name>displayclientalert</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>

  <!-- Common Validator Attributes -->
  <attribute>
     <name>id</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
     <name>name</name>
     <required>true</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
     <name>controltovalidate</name>
     <required>true</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
     <name>enabled</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
     <name>nlsid</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
     <name>errormessage</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
     <name>visible</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
     <name>style</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
  <attribute>
     <name>cssclass</name>
     <required>false</required>
     <rtexprvalue>true</rtexprvalue>
  </attribute>
</tag>


                            

List Box Select Limit Validator Control

                                
/**
 * Copyright (c) Blue Fish Development Group 1996-2004. All rights reserved.
 */

package com.bluefishgroup.wdk.validator;

import com.documentum.web.form.control.ListBox;
import com.documentum.web.form.control.validator.BaseValidator;

/**
 * Validator implementation limits the number of selected options in a
 * multiselect list box control.
 */
public class ListBoxSelectLimitValidator extends BaseValidator {

  /** the max number of selected options */
  private int mMaxSelected = 0;

  /** whether to enable client-side validation */
  private boolean mValidateAtClient = false;

  /** whether to display an alert in the client side validation */
  private boolean mDisplayClientAlert = false;

  /**
   * Gets the maximum number of selected options.
   * 
   * @return the max number of selected options
   */
  public int getMaxSelected() {
    return mMaxSelected;
  }

  /**
   * Sets the maximum number of selected options.
   * 
   * @param max number of selected options
   */
  public void setMaxSelected(int maxSelected) {
    mMaxSelected = maxSelected;
  }

  /**
   * Gets whether to use client-side validation javascript.
   * 
   * @return whether to use client-side validation javascript
   */
  public boolean getValidateAtClient() {
    return mValidateAtClient;
  }
  
  /**
   * Sets whether to use client-side validation javascript.
   * 
   * @param validateAtClient whether to use client-side validation
   */
  public void setValidateAtClient(boolean validateAtClient) {
    mValidateAtClient = validateAtClient;
  }

  /**
   * Gets whether to display an alert in the client side validation.
   * 
   * @return whether to display an alert in the client side validation
   */
  public boolean getDisplayClientAlert() {
    return mDisplayClientAlert;
  }
  
  /**
   * Sets whether to display an alert in the client side validation.
   * 
   * @param displayClientAlert whether to display an alert
   */
  public void setDisplayClientAlert(boolean displayClientAlert) {
    mDisplayClientAlert = displayClientAlert;
  }
  
  /**
   * Returns true if the control is a listbox whose number of selected
   * items is below the set limit, and false otherwise.
   * 
   * @return boolean true if the listbox item count is below the limit
   */
  protected boolean doValidate() {
    boolean isValid = false;
    Control control = getControlToValidate();
    
    if ( control instanceof ListBox ) {
      String[] selectedOptions = getPageContext().getRequest()
          .getParameterValues(control.getElementName());

      isValid = (selectedOptions != null) && 
                (selectedOptions.length <= mMaxSelected);
    }
    
    return isValid;
  }

}


                            

List Box Select Limit Validator Control Tag

                                
/**
 * Copyright (c) Blue Fish Development Group 1996-2004. All rights reserved.
 */

package com.bluefishgroup.wdk.validator;

import java.io.IOException;
import javax.servlet.jsp.JspWriter;

import com.documentum.web.form.Control;
import com.documentum.web.form.control.validator.BaseValidatorTag;
import com.documentum.web.util.StringUtil;

/**
 * Validator tag implementation limits the number of selected options in a
 * multiselect list box control.
 */
public class ListBoxSelectLimitValidatorTag extends BaseValidatorTag {

  /** the max number of selected options */
  private Integer mMaxSelected = null;

  /** whether to enable client-side validation */
  private Boolean mValidateAtClient = null;

  /** whether to display an alert in the client side validation */
  private Boolean mDisplayClientAlert = null;

  /**
   * Set the maximum number of selected options.
   * 
   * @param max number of selected options
   */
  public void setMaxselected(int maxSelected) {
    mMaxSelected = new Integer(maxSelected);
  }

  /**
   * Sets whether to use client-side validation javascript.
   * 
   * @param validateAtClient whether to use client-side validation
   */
  public void setValidateatclient(boolean validateAtClient) {
    mValidateAtClient = new Boolean(validateAtClient);
  }

  /**
   * Sets whether to display an alert in the client side validation.
   * 
   * @param whether to display an alert in the client side validation
   */
  public void setDisplayclientalert(boolean displayClientAlert) {
    mDisplayClientAlert = new Boolean(displayClientAlert);
  }

  /**
   * Release the tag state
   */
  public void release() {
    mMaxSelected = null;
    mValidateAtClient = null;
    mDisplayClientAlert = null;
  }

  /**
   * Get the control class.
   * 
   * @return the class of control to create
   */
  protected Class getControlClass() {
    return ListBoxSelectLimitValidator.class;
  }

  /**
   * Set the control properties.
   * 
   * @param control the control instance
   */
  protected void setControlProperties(Control control) {
    super.setControlProperties(control);

    ListBoxSelectLimitValidator val = (ListBoxSelectLimitValidator) control;

    // Set control properties from the tag arguments
    if (mMaxSelected != null) {
      val.setMaxSelected(mMaxSelected.intValue());
    }
    
    if (mValidateAtClient != null) {
      val.setValidateAtClient(mValidateAtClient.booleanValue());
    }
    
    if (mDisplayClientAlert != null) {
      val.setDisplayClientAlert(mDisplayClientAlert.booleanValue());
    }
  }
  
  /**
   * Render the control HTML.
   *
   * @param out the jsp writer
   * @throws IOException if an exception occurs
   */
  protected void renderEnd(JspWriter out) throws IOException {
    ListBoxSelectLimitValidator val = (ListBoxSelectLimitValidator) getControl();

    if (val.isVisible() && val.getValidateAtClient()) {
      renderClientSideValidation(out);
    }
    
    super.renderEnd(out);
  }
  
  /**
   * Render the client-side validation JavaScript.
   *
   * @param out the jsp writer
   * @throws IOException if an exception occurs
   */
  protected void renderClientSideValidation(JspWriter out) throws IOException {
    ListBoxSelectLimitValidator val = (ListBoxSelectLimitValidator) getControl();
    
    StringBuffer buf = new StringBuffer();

    String  errorMessage = StringUtil.escape(StringUtil.escape(val.getLabel(), '\\'), '\'');
    String  controlName  = val.getControlToValidate().getElementName();
    boolean displayAlert = val.getDisplayClientAlert();
    int max = val.getMaxSelected();

    buf.append("\n<script language='javascript'>\n");

    buf.append("  var dropDownList = null;\n");
    buf.append("  var dropDownLists = document.getElementsByTagName('SELECT');\n");

    buf.append("  for ( var i = 0; i < dropDownLists.length && !dropDownList; i++ ) {\n");
    buf.append("    if (dropDownLists[i].name == ‘”).append(controlName).append(”‘)\n”);
    buf.append(”      dropDownList = dropDownLists[i];\n”);
    buf.append(”  }\n”);

    buf.append(”  if ( dropDownList ) {\n”);
    buf.append(”    dropDownList.setAttribute(’maxSelected’,”).append(max).append(”);\n”);
    buf.append(”    var options = dropDownList.options;\n”);

    buf.append(”    // init each option with its selected (keeper) status\n”);
    buf.append(”    for ( var i = 0; i < options.length; i++ )\n”);
    buf.append(”      options[i].setAttribute(’keeper’, options[i].selected);\n”);

    buf.append(”    dropDownList.onchange = // assign onchange handler function\n”);
    buf.append(”      function() {\n”);
    buf.append(”        var max = this.getAttribute(’maxSelected’);\n”);
    buf.append(”        var options = this.options;\n”);
    buf.append(”        var counter = 0;\n”);

    buf.append(”        // count the total selected, exit loop if max exceeded\n”);
    buf.append(”        for ( var i = 0; i < options.length && counter <= max; i++ )\n”);
    buf.append(”          if (options[i].selected) counter++;\n”);

    buf.append(”        if ( counter > max ) { // too many, revert selection\n”);

    buf.append(”          for ( var i = 0; i < options.length; i++ )\n”);
    buf.append(”            options[i].selected = (new String(options[i].getAttribute(’keeper’)) == ‘true’);\n”);
    
    if (displayAlert) {
      buf.append(”          alert(’”).append(errorMessage).append(”‘);\n”);
    }

    buf.append(”        } else { // set ‘keeper’ status on the selected options\n”);

    buf.append(”          for ( var i = 0; i < options.length; i++ )\n”);
    buf.append(”            options[i].setAttribute(’keeper’, options[i].selected);\n”);
    buf.append(”        }\n”);
    buf.append(”      }\n”);
    buf.append(”  }\n”);
    buf.append(”</script>\n”);
    
    out.write(buf.toString());
  }
}


                            

Conclusion

Validation ensures that your controls are delivered good data. Validation allows users to fix malformed data, and client-side validation alerts users immediately, before bad data is submitted to the server.

The custom validator in this article takes advantage of the WDK 5 validation framework’s base classes to build a simple reusable validator, complete with client-side validation, in only a few hours.

 Votes | Average: 0 out of 5 Votes | Average: 0 out of 5 Votes | Average: 0 out of 5 Votes | Average: 0 out of 5 Votes | Average: 0 out of 5 (0 votes, average: 0 out of 5)
Loading ... Loading ...

Comment on this article:

You must be logged in to post a comment.

Notification

Subscribe to our newsletter to be notified when new articles are posted. You can unsubscribe at any time.