Validation Strategy in WDK

Share This Post

Introduction

The WDK framework provides some powerful and versatile tools for handling validation of user input. There are
some limitations to the validation framework, but once you learn your way around some of its quirks, it can be
powerful and can help streamline input validation.

This article provides an overview of the WDK Validation Framework, along with some
general tips for getting the most out of the WDK validators and knowing how to work around
limitations. If you are looking for a discussion of the various validators WDK provides and
how to use them, you may want to read Validation in WDK.

The strategies and tips discussed in this article are based on WDK 5.2.5, although it is likely that much of
the content will remain relevant into future versions of WDK.

Background

The WDK validation framework consists primarily of validators, which are special controls which are used to
validate other controls.

Documentum provides a wide array of validator implementations for many of their controls, but there is
nothing preventing you from developing your own validators, if necessary.

A typical validator control – like all WDK controls – is specified by a tag class, a control class, and a
tag definition.

This article, however, will focus exclusively on using the existing validators and validation
framework.

Unless you are looking to write your own validators or modify the existing ones, you will not need to know
much about the Java classes behind your validators. Instead, you should focus on familiarizing yourself with the
different validator tags themselves.

The Blue Fish article “Validation in WDK” provides a good overview of the various validators, and of
course the WDK documentation provides a complete validator reference.

How WDK Validation Works

Validators are specified on the JSP page for your component, using standard validator
tags. For example, the tag below might be used to validate that the control “username” is not
empty:

<dmf:requiredfieldvalidator indicator='*'
cssclass='error'
name='usernameRequiredValidator'
controltovalidate='username'
nlsid='LABEL_REQUIRED_INPUT' />

When the tag is rendered, it either evaluates to the indicator (if the field is valid or
if the validator has never been called) or the error message (if the field is invalid).

Through the mechanics of the WDK form processing framework, the validators you specify
are executed by the containing component’s validation methods when the form is
submitted.

By default, all of a component’s visible validators are executed when a server-side
event is fired. (See Turning Off Validation below, for details on
how to override this default behavior.)

The validators are executed in the order in which they were added to the component, one
by one. If a validator fails, its state is changed to invalid; the next time the component is
rendered, any failed validators will display their error messages.

Note that the validators are evaluated before the event handler is called.
By the time the event handler method is called, the validators have all been evaluated, and
the component’s valid flag has been set.

Validation failure does not automatically stop your event from being executed! You must
explicitly check whether validation failed or not using the Component method getIsValid.

There is no way to set a validator back to its valid state once it has evaluated as
invalid. In fact, the only way to get a validator to evaluate to valid once it has evaluated
to invalid is to populate the control with valid data and execute the validator. This means
that once your event is fired and the validators are evaluated, any invalid validator will
display its error message the next time the component is rendered.

There are two important things to understand about WDK Validation that may not be immediately apparent:

  1. All validation takes place on the server, not the client.
  2. A component must be rendered again after validation in order for validation messages to be displayed.

All validation happens at the server. This means that in order for validation rules to be
processed, a server-side event must be fired; it also means that, unless you set your
validation up to do otherwise, any time a server-side event is processed, your validators
will be evaluated. This can be frustrating when some of your events should trigger validation
and others should not. (But don’t worry, this article will cover how to get around that.)

Validation error messages are displayed in place of the validator tags themselves, but only
if the component is allowed to render again. This means that if you want validation to actually
stop an event from jumping to another component and instead display the validation messages,
you must explicitly check the validity of the component in your event handler and make sure the
event handler returns without jumping somewhere new (or doing anything else it shouldn’t do if
input is invalid).

Example 1: Basic Validation, Validator Visibility

In this example, we will:

  1. See how a basic required validator is evaluated.
  2. Observe that validators on hidden panels are not evaluated.

Suppose we have a form with several required inputs and two buttons: Submit and Validate.
When a user clicks the Submit button, the inputs should be validated and then the inputs should
be processed; their values will determine which component to jump to. When the user clicks Validate,
the inputs should simply be validated, with any error messages displayed to the user.

The solution to this example is simple. Once we have developed our JSP page with the various
input controls, validators, and buttons, we must implement two event handlers: onSubmit and onValidate.
When any event is fired on our form, validation will happen automatically. Our onValidate method can therefore
be empty. The onSubmit method, however, will have to check whether validation succeeded or not using the
public method getIsValid. If the input was valid, the event handler can jump to a new component based on
the input; if the input is invalid, the event handler can simple return, which will cause the WDK
framework to render the page again, with error messages prominently displayed.

The files below provide a basic implementation of the solution described above.

You may wish to experiment with the component from the example. Notice how the validator
on the

Turning Off Validation

Fortunately, WDK provides a way to only execute validators for certain events. By
default, the WDK framework automatically executes all visible validators contained by a
component when any event on that component is triggered. By setting the validation
attribute to false in your
<dmf:webform> tag, you can instruct the WDK not to perform validation
automatically. Then you can manually call the validate and
getIsValid methods from your event handlers as needed.

Example 2: Turning Automatic Validation Off, Using Manual Validation

In this example, we will:

  1. See how the <dmf:webform> tag attribute validation can be
    used to turn off automatic validation.
  2. See how to call the validate method to manually execute component validation as needed.

Suppose we have a form with several inputs on it, similar to the form in Example 1.
The two buttons on this form, however, are: Submit and Refresh. When a user
clicks the Submit button, the onSubmit event handler method is called, and it
processes the required data from the form. When the user clicks the Refresh button, the
onRefresh event handler is called, and some business logic is executed to update
some of the values displayed by the component.

The form may have “required” user input fields on it, but we probably don’t want to
display error messages for empty fields when the user clicks Refresh. However, we do need for
validation rules to be evaluated prior to processing of the data when the user clicks Submit.
The solution is to turn off automatic validation using the <dmf:webform> validation attribute, then add calls to the public methods validate
and getIsValid at the beginning of the onSubmit event
handler.

The files below provide a basic implementation of the solution described above.

Note: You may have noticed that there is a protected method validate(boolean) in
addition to the public validate() method. This is the method that is actually
called by the WDK framework to evaluate the validators. The boolean argument instructs the
method whether or not to ignore the validation attribute setting in the
<dmf:webform> tag. If this method is called with an argument of
true, the method will ignore any validation attribute from the
<dmf:webform> tag and evaluate the validators no matter what. This is what
happens when you call the public validate method. When the WDK framework calls
this method, though, it passes in a boolean argument of false, which means the
method will obey the validation attribute from <dmf:webform> and
skip the validators if validation attribute is set to false. (We
will discuss these validate methods in more detail later.

Sometimes, simply turning validation off and calling the validate method(s) directly
is not sufficient, especially for more complex components. Perhaps certain validators
should only be evaluated if certain business rules are met. Or maybe some of the validators
should be run for one set of events, and different validators should be evaluated for another
set of events. In these situations, it may be necessary to override one or both of the
validate methods in your component class.

The protected method validate(boolean) is implemented in the
Form class as well. This is the method which the WDK framework calls to validate
the form when an event is fired (before it passes control to your event handler). Its boolean
argument instructs the method whether or not to ignore the validation attribute of the <dmf:webform>
tag. If this method is called with an argument of false, then the validators are only evaluated
if the <dmf:webform> validation attribute is set to true (or not set at all, since it defaults to true).
If this method is called with an argument of true, then the framework ignores the validation
flag and evaluates the validators no matter what.

To evaluate the validators, the method simply goes through all the enabled validators in
the component and evaluates them one by one. If any of the validators evaluates to
false, then this method sets the isValid flag on the component to
false.

The public method validate() is implemented in the Form class.
It simply calls the protected method validate(boolean) with an argument of
true, instructing it to execute all validators regardless of whether validation
has been turned off using the validation attribute of the <dmf:webform> tag.

Although, the isValid is a private member of the Form class,
you can set it to false by calling the protected Form method
setInvalid. In this way it is possible to completely override the protected
method validate(boolean) to execute any, all, or none of the validators as
desired, calling setInvalid if the form should be considered invalid (which can
then be checked later using getIsValid). The getValidators and
getContainedControls methods might prove useful in this endeavor.

Unfortunately, WDK provides no way to set the component state back to ‘valid’ again,
which means that once you have set the component invalid using setInvalid, there is no way to
reset the state. The only way to get it back to valid is for the base Form class validate
method to be called and for all enabled validators to return true.

This suggests two interesting ways of resetting an invalid component back to valid.

If you have already turned off automatic validation using the <dmf:webform>
validation
attribute, then it’s easy to get the validate method to set the component
state to valid. Simply call the protected validate method from the Form class with the
argument false. This allows the validate method to skip the validators, since automatic
validation is turned off, and it will automatically set the component isValid flag back to
true.

If you have not turned off automatic validation using the <dmf:webform>
validation
attribute, it’s a little more complicated. Because the only way to set the
isValid flag is to call WDK’s protected validate method, which in turn evaluates all enabled
validators, we must find a way to disable all validators prior to calling this method. One
fairly simple, though not terribly intuitive solution, could be the following:

  1. Place all validators into a single panel (remember, panels can be nested,
    so you could still maintain the existing panel model on your page).
  2. Set that panel to hidden, which effectively disables all those validators.
  3. Call the Form.validate method, which will only evaluate enabled validators,
    of which there are none, and so it will set the component state back to valid.

At this point, you might be asking why you need to rely on the Form class’s
implementation of the valid flag at all. What’s to stop us from abandoning the WDK validation
methods entirely and calling all validator controls directly? Rather than go through all this
rigamorale just to change the Form class’s private implementation of a boolean flag, couldn’t
we just as easily implement the valid flag within our own class and call the validators
ourselves?

The answer is yes, we could. And in many situations, this is the best route to take. But
keep in mind that in order for your component to function properly inside of some WDK
containers, it may be necessary to maintain the contract that validate and
getIsValid do what they claim to do; any customized validation you do should fit
into this model if you expect it to work within the larger context of some containers.

There is nothing to stop us, however, from overriding validate(),
validate(boolean), setInvalid(), and getIsValid() to
rely on our own member fields for validity state. As long as we maintain the contract of
those four methods, we should be in good shape. Of course, if somewhere inside the Form class
there are other methods which are checking or altering the isValid flag directly, we could
run into trouble. But experience suggests this is probably nothing to be too concerned
about.

Sometimes, it may even be desirable to abandon the existing validate method and provide
your own way of executing validators.

Note: There is nothing to stop you from getting a specific validator by name and evaluating it
directly, with validation turned off in <dmf:webform> and no calls to the
built-in validate methods. Sometimes this can be very useful, but usually a more general
approach is recommended.

Example 3: Overriding Validation Methods

In this example, we will:

  1. See how to override WDK validation methods in order to implement customized validation.

Suppose we have a form with several inputs on it. Like the form in Example 2, we have two
buttons: Submit and Refresh. In this example, however, our input is a little more complex.
All inputs are required, but input1 should only be validated if
checkbox1 is checked. We need validation which is smart enough to only call the
validator for input1 if checkbox1 is checked; if
checkbox1 is not checked, the validator for input1 should not be
evaluated at all.

To accomplish this, we will first want to turn automatic validation off in the
<dmf:webform> tag. Our onRefresh and onSubmit
methods should be the same as in Example 2; only the event handler for the Submit button
should call validate() method. However, in order for the validate method to
behave correctly and only validate input1 if checkbox1 is checked,
we must override it and implement our own validation logic.

Since we are manually calling the public validate method from our onSubmit event handler
method, we might like to override the public validate() method. This would be a
mistake; if for some reason we ever turn automatic form validation back on, it would bypass
our public method and call the protected validate method directly, breaking our
checkbox-based validation rule. Therefore, we should instead override the protected
validate(boolean) method.

There are a variety of ways to implement the checkbox-based evaluation of the validator.
The example code shows an somewhat simple approach: our validate(boolean) method
leverages the helper method deepValidate, which goes through all the validators
in the component and evaluates them one by one, unless it finds a validator with the specific
name ‘input1_reqval’, which it skips if the checkbox is not checked. In practice, this is a
somewhat fragile implementation: if someone renames the validator, it breaks, and it is not
particularly easy to apply it to multiple inputs. But for the purposes of this article, the
sample implementation will suffice.

One thing you may notice about the validate(boolean) method in the sample
code is that it makes a call to the super.validate(boolean) method. This is due
to the limitation discussed previously. Once the component has been set invalid, there is no
way for us to set it back to valid directly, even when the form is submitted again! It is
necessary, therefore, to get the super.validate(boolean) method to set it to
valid for us. Since in the example we have already turned validation off using the
<dmf:webform> tag, we know that calling validate(false) will
set the component back to valid, since it will skip all validators. In this way, we are able
to reset the component to valid prior to doing our custom validation with
deepValidate().

(If we had a component where we did not turn validation off, we would have to try
something more involved to reset the component state to valid, such as placing all validators
on a panel which we could make invisible prior to calling the super.validate
method.)

The files below provide a basic implementation of the solution described above.

Conclusion

The WDK Validation Framework provides a handy way to implement server-side input validation. There are
some limitations, but with the right workarounds and a good understanding of how the validation framework
operates, these limitations are manageable.

More To Explore

b2b auto pay

B2B Auto Pay: Automation Use Cases

Migrating a B2B “Auto Pay” Program Companies migrating to SAP often have daunting challenges to overcome in Accounts Receivable as part of the transition. You might have different divisions running

ArgonDigital | Making Technology a Strategic Advantage