OpenSymphony's
WebWork is a web
application framework designed to keep productivity high and the
code simple. It has gained popularity for several reasons, including
its integration with Spring, a powerful tag
library, and OGNL
support. Its powerful validation framework is borrowed from another
OpenSymphony project, XWork.
In this article, we will explore the various validation features
of WebWork/XWork, including custom and conditional validation. A
sample application that contains working examples of the different
validation techniques is also included. I will also show how to
perform "re-usable validation" using WebWork's visitor validation.
This article assumes that you are somewhat familiar with WebWork
and will focus on the validation aspects of the framework rather
than the basics.
Setting Up the Sample Application
You can download the sample application from the Resources section. The sample application uses
WebWork 2.2
Beta 3, which comes packaged with XWork 1.0.5. The
build.xml file has instructions on how to make the .war
file using Apache Ant. The .war
file can be deployed in any supporting servlet container. I'm using
Apache Tomcat 5.5.12.
Copying the .war file into Tomcat's webapps directory should
deploy the application, which can then be accessed at the following
URL:
http://localhost:8080/webworkapp
If you see a listing of examples by navigating to this page, all
is well.
Manually Validating Forms
The straightforward way to validate user input is to write Java
code to check the request parameters. WebWork allows you to do this
using two different methods.
Validating Inside the execute() Method
The simplest way to validate user input is to verify the request
parameters inside of the execute() method of your WebWork
actions, as shown in the following example
(com...ex1.actions.UserSignupAction).
However, this technique involves putting validation code in the
execute() method, which is undesirable as it mixes
business logic with validation. A good alternate is to have your
action class implement the Validatable interface.
Implementing the Validatable Interface
Instead of validating inside the execute() method,
you can have the action class implement the
Validatable interface, which requires the implementing
class to define a method with the following signature:
public void validate();
As shown below, the validation code for the action resides in
validate() instead of execute(), thus
separating validation from business logic.
public String execute() {
return SUCCESS;
}
public void validate() {
User user = getUser();
if (StringUtils.isBlank(user.getName())) {
addActionError(getText("user.name.empty"));
}
if (StringUtils.isBlank(user.getAddress())) {
addActionError(getText("user.address.empty"));
}
}
Even though the validation code has moved to a much more
suitable place, we still find ourselves doing too much work by
manually comparing request parameters to determine the validity of
our form input. Fortunately, WebWork provides a finely tuned
validation framework, which helps developers avoid the chore of
writing code for each validation scenario.
Using Built-in Validators
Using built-in validation is a two-step process:
You must tell WebWork the action that you want to validate.
Accomplished via interceptors.
You must tell WebWork what the validation rules are.
Accomplished by specifying rules in an XML file.
Configuring Interceptors
One of the concepts at the foundation of WebWork is that of
interceptors. Interceptors allow various tasks to be
performed when an action is invoked. Once such task is validation.
When we want validation to occur for our actions, we must ensure
that WebWork's validator interceptor is in the interceptor stack
specified in xwork.xml.
The built-in validationWorkflowStack includes the
validator stack and will suffice for our validation needs. Instead
of specifying the validationWorkflowStack for each
action, I've made it the default for all actions by using the
<default-interceptor-ref> element.
However, we don't want to perform validation for all actions
(e.g., when simply viewing the form), and for these cases, I've
explicitly overridden the validationWorkflowStack with
basicStack as shown below:
This might not be ideal in terms of dealing with the workflow of
your application, but it serves its purpose in the sample
application. You should have a good grip on interceptors
before you start working with WebWork.
Tip: In many cases, it is desirable to write a custom
interceptor that ignores validation on all GET requests, thus
saving the chore of having to specify a basicStack
interceptor for each GET action.