Developing Web Applications using JavaServer Faces: Part 2

Exclusive offer: get 50% off this eBook here
Java EE 5 Development with NetBeans 6

Java EE 5 Development with NetBeans 6 — Save 50%

Develop professional enterprise Java EE applications quickly and easily with this popular IDE

$29.99    $15.00
by David R. Heffelfinger | September 2009 | Open Source

In this article series by David Heffelfinger, we have explained how NetBeans can help us easily develop web applications that take advantage of the JavaServer Faces framework.

In this part of the article series, we will discuss the following:

  • Implementing custom JSF validators
  • Displaying tabular data in our pages by dragging-and-dropping the JSF Data Table item from the NetBeans palette into our page

Read Developing Web Applications using JavaServer Faces: Part 1 here.

JSF Validation

Earlier in this article, we discussed how the required attribute for JSF input fields allows us to easily make input fields mandatory.

If a user attempts to submit a form with one or more required fields missing, an error message is automatically generated.

Java EE 5 Development with NetBeans 6

The error message is generated by the <h:message> tag corresponding to the invalid field. The string First Name in the error message corresponds to the value of the label attribute for the field. Had we omitted the label attribute, the value of the fields id attribute would have been shown instead. As we can see, the required attribute makes it very easy to implement mandatory field functionality in our application.

Recall that the age field is bound to a property of type Integer in our managed bean. If a user enters a value that is not a valid integer into this field, a validation error is automatically generated.

Java EE 5 Development with NetBeans 6

Of course, a negative age wouldn't make much sense, however, our application validates that user input is a valid integer with essentially no effort on our part.

The email address input field of our page is bound to a property of type String in our managed bean. As such, there is no built-in validation to make sure that the user enters a valid email address. In cases like this, we need to write our own custom JSF validators.

Custom JSF validators must implement the javax.faces.validator.Validator interface. This interface contains a single method named validate(). This method takes three parameters: an instance of javax.faces.context.FacesContext, an instance of javax.faces.component.UIComponent containing the JSF component we are validating, and an instance of java.lang.Object containing the user entered value for the component. The following example illustrates a typical custom validator.

package com.ensode.jsf.validators;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.html.HtmlInputText;
import javax.faces.context.FacesContext;
import javax.faces.validator.Validator;
import javax.faces.validator.ValidatorException;
public class EmailValidator implements Validator {
public void validate(FacesContext facesContext,
UIComponent uIComponent, Object value) throws
ValidatorException {
Pattern pattern = Pattern.compile("w+@w+.w+");
Matcher matcher = pattern.matcher(
(CharSequence) value);
HtmlInputText htmlInputText = (HtmlInputText) uIComponent;
String label;
if (htmlInputText.getLabel() == null ||
htmlInputText.getLabel().trim().equals("")) {
label = htmlInputText.getId();
} else {
label = htmlInputText.getLabel();
}
if (!matcher.matches()) {
FacesMessage facesMessage =
new FacesMessage(label +
": not a valid email address");
throw new ValidatorException(facesMessage);
}
}
}

In our example, the validate() method does a regular expression match against the value of the JSF component we are validating. If the value matches the expression, validation succeeds, otherwise, validation fails and an instance of javax.faces.validator.ValidatorException is thrown.

The primary purpose of our custom validator is to illustrate how to write custom JSF validations, and not to create a foolproof email address validator. There may be valid email addresses that don't validate using our validator.

The constructor of ValidatorException takes an instance of javax.faces.application.FacesMessage as a parameter. This object is used to display the error message on the page when validation fails. The message to display is passed as a String to the constructor of FacesMessage. In our example, if the label attribute of the component is not null nor empty, we use it as part of the error message, otherwise we use the value of the component's id attribute. This behavior follows the pattern established by standard JSF validators.

Before we can use our custom validator in our pages, we need to declare it in the application's faces-config.xml configuration file. To do so, we need to add a <validator> element just before the closing </faces-config> element.

<validator>
<validator-id>emailValidator</validator-id>
<validator-class>
com.ensode.jsf.validators.EmailValidator
</validator-class>
</validator>

The body of the <validator-id> sub element must contain a unique identifier for our validator. The value of the <validator-class> element must contain the fully qualified name of our validator class.

Once we add our validator to the application's faces-config.xml, we are ready to use it in our pages.

In our particular case, we need to modify the email field to use our custom validator.

<h:inputText id="email" label="Email Address"
required="true" value="#{RegistrationBean.email}">
<f:validator validatorId="emailValidator"/>
</h:inputText>

All we need to do is nest an <f:validator> tag inside the input field we wish to have validated using our custom validator. The value of the validatorId attribute of <f:validator> must match the value of the body of the <validator-id> element in faces-config.xml.

At this point we are ready to test our custom validator.

Java EE 5 Development with NetBeans 6

When entering an invalid email address into the email address input field and submitting the form, our custom validator logic was executed and the String we passed as a parameter to FacesMessage in our validator() method is shown as the error text by the <h:message> tag for the field.

Java EE 5 Development with NetBeans 6 Develop professional enterprise Java EE applications quickly and easily with this popular IDE
Published: October 2008
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

Displaying Tabular Data

JavaServer Faces includes the <h:dataTable> tag that makes it easy to iterate through an array or collection of objects. With NetBeans, a data table tag can be added to a page by simply dragging the JSF Data Table item from the NetBeans palette into our page. In order to demonstrate the usage of this tag, let's create a new Web Application project, and add a new JSP named registrationlist.jsp to it.

Java EE 5 Development with NetBeans 6

After dragging the JSF Data Table item into the appropriate location in our registrationlist.jsp page, the following window pops up.

Java EE 5 Development with NetBeans 6

We can either select to create an Empty Table or a Table Generated from an Entity Class.

An Entity Class refers to a Java Persistence API (JPA) entity.

Selecting to create an empty table generates the following markup in our page:

<h:form>
<h:dataTable value="#{arrayOrCollectionOf}"
var="item">
</h:dataTable>
</h:form>

Notice that NetBeans automatically wraps the generated <h:dataTable> tag in an <h:form> tag. The <h:form> tag is necessary if we plan to have any input fields in our table. Since this is not the case in our example, we can safely delete it.

The value of the value attribute of <h:dataTable> typically resolves to an array or collection of objects. NetBeans places the placeholder value binding expression #{arrayOrCollectionOf} as its value; we must replace this with a value binding expression resolving to one of the appropriate types.

The value of the var attribute of <h:dataTable> is used to refer to the current element in the table. As we iterate through the elements of the array or collection from the value attribute, we can use the value of the item attribute to refer to the current element in the array or collection.

We need to add a <h:column> tag inside the <h:dataTable> tag for each column we wish to add to the table. The following example illustrates typical usage of <h:dataTable> and <h:column>.

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=UTF-8">
<title>JSP Page</title>
</head>
<body>
<f:view>
<h:form>
<h:dataTable
value=
"#{RegistrationListController.registrationBeanList}"
var="item" border="1" cellspacing="0"
cellpadding="5">
<h:column>
<f:facet name="header">
<h:outputText value="Salutation"/>
</f:facet>
<h:outputText value="#{item.salutation}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="First Name"/>
</f:facet>
<h:outputText value="#{item.firstName}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Last Name"/>
</f:facet>
<h:outputText value="#{item.lastName}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Age"/>
</f:facet>
<h:outputText value="#{item.age}"/>
</h:column>
</h:dataTable>
</h:form>
</f:view>
</body>
</html>

In this example, we will be iterating through a collection of RegistrationBeanobjects. The objects will be stored as a property named registrationBeanList of type java.util.List in a managed bean called RegistrationListController, therefore we set the value of the value attribute of <h:dataTable> to #{RegistrationListController.registrationBeanList}.

NetBeans creates a sensible value for the var attribute, therefore we leave it as is.

<h:dataTable> contains a few attributes that allow us to control the look of the generated table. These attributes are identical to attributes in a standard HTML table. In our example, we set a border of 1 pixel in the table by setting the value of the border attribute to 1. We set the spacing between table cells to zero by setting the cell spacing attribute to 0. We also set the spacing (padding) inside table cells to 5 pixels by setting the cell padding attribute to 5.

The complete list of attributes for <h:dataTable> can be seen by using code completion (Ctrl+Space).

Since our table will have four columns, we need to add four nested <h:column> tags into our data table (one for each column).

Notice each <h:column> tag has a nested <f:facet> tag. JSF tags might define one or more facets. Facets are components that are rendered differently from other components in the parent component. Each facet must have a unique name for each parent component. <h:column> defines a facet with a name of header, this facet will be rendered as the header of the generated table. To render a facet inside a JSF component, the <f:facet> tag is used. In our example we give our facet the name of header by assigning this value to its name property. At runtime, JSF renders the tag inside <f:facet> as the header of the column rendered by the facet's parent <h:column> tag. Each <f:facet> tag must have a single child tag, which can be any HTML JSF tag.

Adding Multiple Child Components to a Facet
Although the <f:facet> tag only accepts a single child component, we can add multiple components to it by nesting them inside an <f:panelGroup> tag.

Although not shown in the example, <h:column> also defines a facet with a name of footer that can be used to render a footer for the column. We simply would add a second facet named footer inside our <h:column> tag.

Next we add the tags that will be displayed as a single cell for the particular column. We can access the current item in the collection or array. We will be iterating, by using the value of the var attribute of <h:dataTable> (item, in our particular example).

In our example we simply display the values for a single property or each item, however any JSF component can be placed inside <h:column>.

Before we can deploy our application and see the above page in action, we need to create the RegistrationListController managed bean.

Recall that the easiest way to create JSF managed beans is by going to File | New, selecting the JavaServer Faces category, and JSF Managed Bean as the file type. This procedure is covered in detail earlier in this article.

Our managed bean is shown next:

package com.ensode.jsf;
import java.util.ArrayList;
import java.util.List;
public class RegistrationListController {
private List<RegistrationBean> registrationBeanList;
public RegistrationListController() {
}
public String populateList() {
registrationBeanList = new
ArrayList<RegistrationBean>();
registrationBeanList.add(populateBean(
"MS", "Carol", "Jones", 35));
registrationBeanList.add(populateBean(
"MRS", "Glenda", "Murphy", 39));
registrationBeanList.add(populateBean(
"MISS", "Stacy", "Clark", 36));
registrationBeanList.add(populateBean(
"MR", "James", "Fox", 40));
registrationBeanList.add(populateBean(
"DR", "Henry", "Bennett", 53));
return "success";
}
public List<RegistrationBean> getRegistrationBeanList() {
return registrationBeanList;
}
public void setRegistrationBeanList(
List<RegistrationBean> registrationBeanList) {
this.registrationBeanList = registrationBeanList;
}
private RegistrationBean populateBean(String salutation,
String firstName, String lastName, Integer age) {
RegistrationBean registrationBean;
registrationBean = new RegistrationBean();
registrationBean.setSalutation(salutation);
registrationBean.setFirstName(firstName);
registrationBean.setLastName(lastName);
registrationBean.setAge(age);
return registrationBean;
}
}

Notice that the bean has a property named registrationBeanList of type java.util.List. This is the property we used as the value of the value property in the <h:dataTable> tag in the page above.

The bean's populateList() method will be called from another JSP via dynamic navigation. This method populates the registrationBeanList property in the bean.

A real application would more than likely retrieve this information from a relational database. To keep our example simple we are simply populating the bean from new instances of RegistrationBean we create on the fly.

Now we need to modify the JSP that will be invoked initially. When creating the project, NetBeans automatically sets it up so that a JSP called welcomeJSF.jsp will be invoked when we point the browser to our application's URL. We need to modify this JSP so that it will invoke the populateList() method of our RegistrationBeanList managed bean when navigating to the page we wrote earlier.

<f:view>
<h:form>
<h:commandLink value="Populate List"
action="#{RegistrationListController.populateList}" />
</h:form>
</f:view>

For brevity, we are only showing the relevant parts of the JSP. Our JSP will have an <h:commandLink> tag used for navigation. <h:commandLink> is functionally equivalent to <h:commandButton>, the main difference is that it is rendered as a link as opposed to a button. The value of the value attribute of <h:commandLink> is used to render the link text; its action attribute is used for navigation. In this case we are using dynamic navigation. When using dynamic navigation, a value binding expression is used as the value of the action attribute. This value binding expression must resolve to a method that returns a String. The method must take no arguments. When using dynamic navigation, the method that the value binding expression resolves to may return different strings depending on its logic. We can have a page navigate to different pages depending on the value returned by this method. To do this we would have to add a <navigation-case> element for each possible value that the method may return.

In our example, the populateList() method of the RegistrationListController managed bean is invoked when a user clicks on the link. This method populates the list that we will iterate through and returns the value of success.

Before we deploy our application, we need to define the navigation between our two pages. Normally this is done by manually editing faces-config.xml. However, when using NetBeans, it can be done graphically in the NetBeans PageFlow editor as explained earlier in this article.

Java EE 5 Development with NetBeans 6

The above screenshot shows the PageFlow editor after connecting the initial page containing the <h:commandLink> that initiates navigation to the page that iterates through the list of RegistrationBean instances, and after changing the default navigation case to success. Notice that the text in the navigation case matches the return value of the populateList() method in the RegistrationListController method. This is how the navigation case is linked to the method's return value.

At this point we are ready to test our application. We can execute the initial welcomeJSF.jsp page by right-clicking on it and selecting Run File.

Java EE 5 Development with NetBeans 6

At this point, the application server is started (if it hadn't been started previously), the application is deployed, and a browser window opens displaying the page.

Java EE 5 Development with NetBeans 6

Here we can see the link that was generated by the <h:commandLink> tag in our JSP. Clicking on that link results in executing the populateList() method in the RegistrationListController managed bean and navigating to the JSP containing the <h:dataTable> tag.

Java EE 5 Development with NetBeans 6

Here we can see the table generated by <h:dataTable>, the headers (Salutation, First Name, Last Name, and Age) are generated by the <f:facet> tags inside each <h:column>. While iterating through the collection of RegistrationBean objects in the registrationBeanList property of the RegistrationListController managed bean, each cell in each row displays the property corresponding to the <c:outputText> tag inside each <c:column> tag in the table.

Summary

In this article series, we saw how NetBeans can help us easily create new JSF projects by automatically adding all required libraries and configuration files.

We also saw how we can create JSF forms for data input and data tables for displaying tabular data by simply dragging and dropping icons from the NetBeans palette into our page.

Additionally, we saw how NetBeans can simplify and significantly speed up development of JSF applications by automatically adding managed bean definitions to the application's <faces-config.xml> configuration file, and by allowing us to graphically define navigation rules by taking advantage of the NetBeans PageFlow editor.

If you have read this article you may be interested to view :

Java EE 5 Development with NetBeans 6 Develop professional enterprise Java EE applications quickly and easily with this popular IDE
Published: October 2008
eBook Price: $29.99
Book Price: $49.99
See more
Select your format and quantity:

About the Author :


David R. Heffelfinger

David Heffelfinger is the Chief Technology Officer of Ensode Technology, LLC, a software consulting firm based in the greater Washington DC area. He has been architecting, designing and developing software professionally since 1995 and has been using Java as his primary programming language since 1996. He has worked on many large scale projects for several clients including the US Department of Homeland Security, Freddie Mac, Fannie Mae, and the US Department of Defense. He has a Masters degree in Software Engineering from Southern Methodist University. David is editor in chief of Ensode.net (http://www.ensode.net), a website about Java, Linux, and other technology topics.

Books From Packt

Flex 3 with Java
Flex 3 with Java

Zend Framework 1.8 Web Application Development
Zend Framework 1.8 Web Application Development

WebSphere Application Server 7.0 Administration Guide
WebSphere Application Server 7.0 Administration Guide

Apache Maven 2 Effective Implementations: RAW
Apache Maven 2 Effective Implementations: RAW

Oracle JRockit: The Definitive Guide
Oracle JRockit: The Definitive Guide

Solr 1.4 Enterprise Search Server
Solr 1.4 Enterprise Search Server

Pentaho Reporting 3.5 for Java Developers
Pentaho Reporting 3.5 for Java Developers

Joomla! 1.5 SEO
Joomla! 1.5 SEO

No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
v
Q
7
h
f
L
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software