Validating and Converting User Input With the JSF Framework
This document is the second installment in the jAstrologer series of JSF tutorials. In the
first installment of the series, you created a simple
web application called jAstrologer. You can download
the project here if you have not run through the first installment. Make sure you undeploy
any other applications with the /jAstrologer context root that you may have already
deployed to the server.
So far the jAstrologer web application does the following:
Presents greeting.jsp, which uses two inputText components to ask for
the user's name and birthday.
Saves the values entered by the user in the properties of the UserBean backing
bean.
Reads the values of the properties from UserBean and displays them in
success.jsp.
But was it really a success? In the application's present state, you do not know. The application
takes any input (or no input at all) and calls it a success. That is why you need to add
validation to the web application. In this tutorial you will do the following:
Make both inputText components required fields, which will automatically validate
that something was input and show error messages if not.
Use a converter to convert the birthday
inputText
field into a java.util.Date object, which in itself checks that the data is a
valid date.
Write some custom error messages to a new properties file, and improve their
general display.
Create a custom validator to check whether input is in the form of a valid email address.
Note: The GlassFish
application server V2 Update Release 2 is optionally included in the Web and Java
EE installation of NetBeans IDE.
Making a Field Required
The first thing you need to do is make sure that the user enters something for the name field.
This is easily accomplished using the required attribute of the inputText
component.
Open greeting.jsp and change the name inputText component as follows
(changes in bold):
You have just given an ID to the name text field, so you can later specify for which component
the message displays. You then specified that the field is required, so the web application will
show the error message if the user does not enter anything. Also, you set the font of the error
message to display in red using the HTML style attribute. JSF tags generally accept all
commonly used HTML attributes.
In the Projects window, right-click the project node and choose Run (F6). The project is
compiled and deployed to the server. Your default browser starts and opens greeting.jsp.
Click Submit without entering a name. You get the following error:
Using a Converter
Consider treating the birthday field as a date and not a random string. The JSF framework
provides a number of converters that you can use to convert text input into object types,
such as booleans or Date objects. In the process of converting the data, the JSF
framework also checks that the data is valid for the type of conversion selected. This is
useful for the birthday input field because you can specify the date format, validate the
input, and get a Date object all at once.
Open greeting.jsp and change the birthday inputText component as follows
(changes in bold):
You have just given an ID to the birthday text field, so you can then specify for which
component the message is displayed. Set the converter to the pattern dd/MM/yyyy.
Anything the user enters that does not match this format will cause the web application
to redisplay greeting.jsp with an error message. You also specified that the
field is required and set error text to red, as you previously did with the name field.
You need to change the type of the birthday property in UserBean.java to
a Date object. Open the UserBean class to make the following changes (in
bold) and add an import statement for java.util.Date:
package astrologer.user;
import java.util.Date;
public class UserBean {
private String name;
private Date birthday;
/** Creates a new instance of UserBean */
public UserBean() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Date getBirthday() {
return birthday;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
}
You can allow the IDE to add required import statements for
you by right-clicking in the Source Editor and choosing Fix Imports (Ctrl-Shift-I).
Run the project. When you try to click Submit without entering a date, you get the following
error message:
If you enter a date in an unaccepted format, you get the following error:
Changing the Default Error Messages
The error messages that are shown for each type of validation error are controlled by the
Message.properties file, which is located in the javax.faces package of
jsf-impl.jar. You can view this file from the Projects window by expanding Libraries
> GlassFish V2 > jsf-impl.jar > javax.faces and double-clicking
Messages.properties.
You can create custom messages for the previously displayed errors by replacing the properties file
used by the application.
In the Projects window, right-click the jAstrologer project node and choose New >
Other. In the New File wizard that displays, select Properties File under the Other
category, and click Next.
In the Name and Location panel of the wizard, name the file MyMessages, type
src/java/astrologer/ui for the Folder, and click Finish. MyMessages.properties
opens in the Source Editor.
Open the Files window (Ctrl-2) and expand the src/java/astrologer/ui folder to
see the file listed.
Copy over the following properties from Messages.properties to MyMessages.properties:
javax.faces.component.UIInput.REQUIRED={0}: Validation Error: Value is required.
javax.faces.converter.DateTimeConverter.DATE={2}: ''{0}'' could not be understood as a date.
javax.faces.converter.DateTimeConverter.DATE_detail={2}: ''{0}'' could not be understood as a date. Example: {1}
Change the values of the properties:
javax.faces.component.UIInput.REQUIRED=Please enter a value for this field.
javax.faces.converter.DateTimeConverter.DATE=Please enter a valid date.
javax.faces.converter.DateTimeConverter.DATE_detail=Please enter a valid date. Example: {1}
Open faces-config.xml (under Configuration Files in the Projects window). If
necessary, click the XML tab in the toolbar above the Source Editor to view the file's
code, and enter the following inside the main faces-config element:
Right-click the project node and choose Run. When you do not enter anything for a required
field or enter an unaccepted date format for the birthday field, the application shows the
following errors:
Note that any messages that you have not specified in your custom properties file will
be taken from the default Messages.properties in jsf-impl.jar.
Creating a Custom Validator
You can code your own validators if the standard JSF validators do not work for you. In this
example, you code a validator that checks a string to see if it is a valid email. To create
a custom validator, you create a class that implements the
javax.faces.validator.Validator
interface, then register the class in faces-config.xml. You can then apply the validator
using the f:validator
tag.
Right-click the project node and choose New > Java Class. Name the class EmailValidator,
create a new package for it by typing in astrologer.validate in the Package field,
and click Finish.
In the newly created file, modify the class declaration to implement Validator as follows:
public class EmailValidator implements Validator {
Click on the light bulb icon that displays in the
Source Editor's left column to display hints for adding the import
statement and generating abstract methods:
Modify the validate() method as follows:
public void validate(FacesContext facesContext,
UIComponent uIComponent, Object value) throws ValidatorException {
//Get the component's contents and cast it to a String
String enteredEmail = (String)value;
//Set the email pattern string
Pattern p = Pattern.compile(".+@.+\\.[a-z]+");
//Match the given string with the pattern
Matcher m = p.matcher(enteredEmail);
//Check whether match is found
boolean matchFound = m.matches();
if (!matchFound) {
FacesMessage message = new FacesMessage();
message.setDetail("Email not valid - The email must be in the format ");
message.setSummary("Email not valid - The email must be in the format ");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(message);
}
}
Right-click in the Source Editor and choose Fix Imports (Ctrl-Shift-I) to add any necessary import statements.
(You should choose to import java.util.regex.Matcher, java.util.regex.Pattern
and javax.faces.application.FacesMessage.)
Open faces-config.xml and add the following code (in bold):
Open greeting.jsp and add a field for entering an email address:
<p>Enter your name:
<h:inputText value="#{UserBean.name}" id="name" required="true"/>
<h:message for="name" /></p>
<p>Enter your email:
<h:inputText value="email" id="email" required="true">
<f:validator validatorId="astrologer.EmailValidator" />
</h:inputText>
<h:message for="email" style="color:red" /></p>
<p>Enter your birthday:
Run the project. When you enter an invalid email address in the field, you get the
following error:
Creating a Custom Converter
Although performing validation using required fields and converters is easy, it is also very
limited. For example, the converter checks that the birthday field is a valid date, but it
does not check whether the date is in the past. To fine-tune how the date is checked, you can
create a custom converter. The custom converter checks that the date is in the correct format
and that it is in the past. If an error is encountered, the converter displays an appropriate
message.
To create a custom converter, you create a class that implements the
javax.faces.converter.Converter
interface and then register the class in faces-config.xml. You can then apply the
converter by using the f:converter
tag.
Right-click the project node and choose New > Java Class. Name the class MyDateConverter,
and create a new package for it by typing astrologer.convert in the Package field.
Click Finish.
In the class declaration, implement Converter as follows (changes in bold):
public class MyDateConverter implements Converter {
Use the IDE hints to add the appropriate import statement and implement abstract methods.
(In the previous section you used IDE hints for this purpose. The
IDE generates two methods: getAsObject() and getAsString().
Modify the getAsObject() method as follows:
public Object getAsObject(FacesContext context, UIComponent component, String value) throws ConverterException {
String pattern = "dd/MM/yyyy";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
Date nDate;
try {
nDate = sdf.parse(value);
} catch (ParseException ex) {
FacesMessage message = new FacesMessage();
message.setDetail("Date is missing or not valid");
message.setSummary("Date is missing or not valid");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ConverterException(message);
}
if(nDate.getTime() > new Date().getTime()){
FacesMessage message = new FacesMessage();
message.setDetail("Date is later than current date");
message.setSummary("Date is later than current date");
message.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ConverterException(message);
}
return nDate;
}
Make the following changes to the getAsString() method:
This document described how to implement validation to user input within a web application.
Specifically, it demonstrated how to make input fields required, and display error messages
when input is lacking. It also showed how to use a converter to convert a string into a
java.util.Date object, which checks if user input was received in the proper format.
Finally, it demonstrated how to add custom validation to a backing bean.
See the official JavaServer
Faces documentation for tutorials, FAQs and articles. The Java
EE 5 Tutorial is a comprehensive resource for learning how to develop web applications.
Refer to it for a more thorough description of custom validators and error messages, and
more generally robust validation.
You can learn more by continuing to the third installment of the jAstrologer series of JSF tutorials:
Introduction to the Struts Web Framework.
An introductory tutorial that describes how to develop web applications using the Struts
framework in the NetBeans IDE.