User input validation is an important part of any Web application's
navigation flow. There are two peculiar tasks that every Web application
performs-check that all required form fields are filled in and in case of any
malformed or erroneous data from the user, redisplay the form with proper error
messages. Using vanilla servlets and JSP pages to counter malformed user input
can be cumbersome and difficult to maintain. On the other hand is JSF that
provides a standard conversion, validation, and messaging framework to validate
user input. In this article, we'll go the JSF way and roll out a JSF
framework-based custom validator.
|
JSF validation approaches
JSF offers rich support for validating user input. Broadly, JSF supports
automatic and custom validations. For example, to enable length validation for
an HTML input text, f:validateLength should be added as a child to h:inputText
tag. Further, you can also validate via automatic 'type conversion'. JSF's type
conversion is very similar to JavaBean's
properties are defined with primitive types such as int, short, long, etc. In
case, there's a conversion error, form is redisplayed. You can also add the
required attribute to any input element to indicate that empty values are
errors.
For trivial applications, automatic JSF conversion and validation is
sufficient to validate user input. Further, you can roll custom validation
techniques for more demanding scenarios. JSF also provides nifty procedures to
avoid displaying verbose messages by changing the default validator messages.
Using custom validator
With a custom validator, we can make sure that the user input is correct and any
malformed data entered by the user results in redisplaying the form. As an
illustration, we'll roll a simple newsletter subscription application wherein
we'll ask the user to enter her first name, last name and e-mail address.
The navigation flow of your applicatrion looks like this and using the MyEclipse IDE, you can visually edit the faces-config.xml file |
We'll write a custom validator that will validate whether the e-mail address
entered by the user is valid. In case of any erroneous data, a Validator
Exception, which wraps a FacesMessage will be thrown. Consider the following JSF
managed bean class, which forms the model component of our application. Also
note that considering the length of all code, we have not given all of it here.
You can find it on this month's PCQ Professional CD.
package com.pcquest.medtracker;
import javax.faces.context.*;
import javax.faces.component.*;
import javax.faces.validator.*;
import javax.faces.application.*;
public final class
NewsletterSubscriptionBean {
private String mailID;
private String firstName;
private String lastName;
public NewsletterSubscriptionBean() {
super();
}
public String getMailID() {
return mailID;
}
public void setMailID(String mailID) {
this.mailID = mailID;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName)
{
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public void validateMailId(FacesContext context,
UIComponent componentToValidate,
Object value)
throws ValidatorException {
String mailID= value.toString();
if (mailID.indexOf("@")==-1) {
FacesMessage message =
new FacesMessage("Invalid Mail ID, pls. try again!");
throw new ValidatorException(message);
}
}
public String subscribeUser() {
return "success";
}
}
Leftmost: Malformed user input; center: Erroneous data entered by the user; Right: Successful registration |
The NewsletterSubscriptionBean. validateMailId() method is used as a custom
validator to validate the user's e-mail address. This method accepts three
arguments: FacesContext- the context implementation, UIComponent- this
identifies the component being validated, and Object- the submitted value. In
case the user entered a wrong e-mail address, this methods wraps a FacesMessage
in a ValidatorException object which is then propagated. Note that the return
type of the validateMailId() method is void; this method does nothing if the
validation suceeds.
Triggeting custom validation
A custom validator method is triggered by a JSP page through JSF Expression
Language or EL. For example, consider the following code fragment, which
presents a JSP view page that accepts user's inputs and puts our validator in
action (for brevity, not all code lines are shown here).
...
.
.
.
/>
id="subscribe" />
Notice the 'required' attribute of the inputText tag above. Utilizing the
required attribute is a form of default validation. If the attribute is 'true',
the corresponding component must have a value.
In case the required attribute is 'false' and no validation has been assigned
to the tag/component, JSF will skip validation for this component and leave the
value and component state unchanged. For the UI component to delegate the
validation task to a custom validator, you must specify the method name
explicitly using JSF EL syntax- #{ManagedBean.someValidatorMethod}.
For example, the above code fragment uses #{NewsletterSubscriptionBean.validateMailId}
to trigger our custom validator. Further, you also need to display a descriptive
message in case the user enters an invalid mail address, and the
does the same.
Defining the navigation rule
Now that we have created our model and view components, the only thing left for
us to do is hook them together with proper navigation cases. We'll use the
MyEclipse IDE for visual editing the 'faces-config.xml' artifact.
Running the application
We'll use MyEclipse to deploy our application to Tomcat 5 and then launch the
server. Point your Web browser to http://localhost:8080/pcquest/subscribe.faces.
The browser output for the same looks as shown below. Note that we are using the
'Faces Servlet' as the controller component of our application; all user
requests ending matching *.faces extension are routed through this front
controller servlet. In the center is the form when the user enters an invalid
mail address. Note that the form is redisplayed with previously entered values
and an appropriate warning message is rendered.
Finally, we'll see our navigation rules kick in as we are validated and
directed to the success.jsp page where the user name is displayed (the rightmost
screen).
Conclusion
From its inception, JSF was designed to support validation rules on a
field-by-field basis. In JSF, components perform syntactic validation typically
during the conversion from a request parameter string value to the native type
of the business data property bound to the component.
For complex business rules, you can develop custom validators.