JSFSkript
JSFSkript
JSFSkript
JavaServer Faces
java.sun.com/javaee/javaserverfaces
May 08
2
Table of Contents
1 Introduction ...............................................................................................................................5
1.1 JSF in Comparison to other Web Frameworks....................................................................................................5
1.1 The JSF Application Structure..............................................................................................................................8
1.2 The JSF Concepts................................................................................................................................................9
1.3 UIComponents.....................................................................................................................................................9
1.4 Renderers...........................................................................................................................................................10
1.5 Validators...........................................................................................................................................................10
1.6 Backing Beans...................................................................................................................................................10
1.7 Converters..........................................................................................................................................................10
1.8 Events and Event Listeners................................................................................................................................10
1.9 Navigation..........................................................................................................................................................10
1.10 The JSF expression language............................................................................................................................11
5 Messaging ...............................................................................................................................35
5.1 Messages...........................................................................................................................................................35
5.2 Overriding standard Messages..........................................................................................................................36
5.3 Constructing Application Messages...................................................................................................................37
3
8 Internationalization .................................................................................................................47
8.1 Load the Resource Bundle.................................................................................................................................47
8.2 Configuring Locales............................................................................................................................................48
8.3 Creating Resource Bundles...............................................................................................................................48
8.4 Using Resource Bundles....................................................................................................................................49
8.5 Constructing Localized Messages .....................................................................................................................49
8.6 Using Localized Message Bundles for Application Messages ..........................................................................51
4
1 Introduction
Web Frameworks
1.1 JSF in Comparison to other Web Frameworks
3
Like the Struts framework, JSF defines a set of JSP tags that generate HTML form elements that
can be bound to JavaBean properties. The greatest advantage that JSF technology has over
Struts is its flexible, extensible UI component model, which includes:
• A standard component API for a wide range of components, including simple ones, such as
input fields, or more complex ones, such as scrollable data tables. Developers can also
create their own components based on the JSF APIs, and many third parties have already
done so and have made their component libraries publicly available (e.g. MyFaces,
http://www.myfaces.org/).
• A separate rendering model that defines how to render the components in various ways.
For example, a component used for selecting an item from a list can be rendered as a
menu or a set of radio buttons.
• An event model that defines how to handle events generated by activating a component,
such as what to do when a user clicks a button or a hyper link.
• Conversion and validation.
Because the JavaServer Faces technology architecture separates the definition of a component
from its rendering, you can render your components in different ways or even for different clients,
such as a WML client. Moreover, the extensible component APIs of JavaServer Faces technology
allow you to extend the standard set of components and create entirely new components. None of
this is possible with Struts. In fact, Struts has no notion of server-side components, which also
means that it has no event model for responding to component events and no facility for saving
and restoring component state. While Struts does have a useful tag library for rendering
components on the page, these components have no object representation on the server and they
can only be rendered to an HTML client.
Another distinct advantage of JavaServer Faces technology is that it has been designed to allow
easy integration into tools. As a result, JavaServer Faces technology already has wide industry
support and is build in several web application development IDEs (Sun Java Studio Creator, IBM
WebSphere Application Developer, Oracle JDeveloper).
5
Web browsers don't know anything about JSF components or events. When a user clicks a button
in a JSF application, it causes a request to be sent from your web browser to the server, or more
precisely to the FacesServlet. JSF is responsible for translating that request into an event that can
be processed by your application logic on the server (usually by the backing bean). JSF is also
responsible for making sure that every UIComponent you have used on your pages is properly
displayed on your browser.
JSF applications run on the server and can integrate with other subsystems like EJBs, web
services or databases.
faces-config.xml is the central configuration file for JSF applications. Here, we define the
navigation rules, the used backing beans and so on.
6
A simple JSF Page
Here is an example of a simple page with a label („Your Name“) with an input text field and a
submit button („Say Hello“).
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" version="2.1">
<jsp:directive.page contentType="text/html"/>
<html xmlns="http://www.w3.org/1999/xhtml">
<head> <title>Hello, world!</title> </head>
<body>
<f:view>
<h:form>
<h:outputText value="Your Name: "/>
<h:inputText value="#{helloBean.name}"/>
<h:outputText value="Your Age: "/>
<h:commandButton value="Say Hello"
action="#{helloBean.sayHello}"/>
</h:form>
</f:view>
</body>
</html>
</jsp:root>
For the web page designer, a JSF page looks similar to a normal HTML or JSP page. As soon as
we define the JavaServer tag namespaces (core and html), all JSF tags can be used. These pages
can also be designed by an IDE like Sun Java Studio Creator, IBM WebSphere or Oracle
JDeveloper.
At runtime, the FacesServlet automatically translates these tags to a HTML form. After translation,
the generated HTML page looks as follows:
<html><head><title>Hello, world!</title></head>
<body>
<form id="main" name="main" method="post"
action="/helloWorld1/faces/hello.jsp"
enctype="application/x-www-form-urlencoded">
<input type="hidden" name="main" value="main" />
<input type="hidden"
id="javax.faces.ViewState" value="j_id1:j_id2" />
<span id="main:o1">Your Name: </span>
<input id="main:i1" type="text" />
<input id="main:submit" type="submit" value="Say Hello"/>
</form></body>
</html>
The outputText is converted to normal text, the inputText to a input tag and the submit button to a
submit input tag.
Hidden input fields are used to transmit state information about the client or server.
7
1.1 The JSF Application Structure
Developing a simple JavaServer Faces application usually requires the following tasks:
• Create the JSP Pages: The JSP Pages using html and core tags.
• Develop the Model Object (business logic)
• Develop the backing beans with the properties as well as the used action methods.
• Add managed bean declarations to the application configuration file (Faces Config). The
configuration file contains the name of the corresponding backing bean.
• Define page navigation in the application configuration resource file
In the JSP Page we use the the unified expression language (EL, cf. Section 1.10) to bind UI
component values and objects to backing bean properties or to reference backing bean methods
from UI component tags.
The HTML Page (with HTML Elements) as well as all the JSF Views (with the necessary UI
Components) are automatically generated form the JSP Page. The Faces Servlet is provided by
the JSF Application and is responsible for the communication between the server and the clients
(Front Controller pattern).
Client Server
Faces
JSP Page
Config
8
1.2 The JSF Concepts
The following is a UML class diagram showing the different concepts of JSF.
The view object contains a tree of UIComponents (output labels, command buttons, text fields, ...),
which are displayed by the dedicated renderer. On user input, the backing beans are automatically
updated. Converters translate and format the components value and generate an error message (if
necessary). Validators verify the value of a component and generate an error message (if
necessary).
In general, JSF applications communicate by events. Backing beans contain event listeners and
action methods. The outcome of an action method can be used to specify the next page to be
shown (navigation). Event listeners consume events and can execute model objects, which
perform the core application logic.
In JSF applications, model objects don't know anything about the user interface. This enforces a
MVC-style architecture.
1.3 UIComponents
Like Swing components, UIComponents are built as JavaBeans. This means, they have properties,
methods, and support event handling. Unlike Swing, JSF UIComponents live on the server side,
not on the client.
Providing these UI elements as components makes development much easier, because the core
functions are encapsulated within a reusable package. In order to use a UIComponent, you just
have to configure some properties, such as the color or the default value, and you don't have to
develop any complicated combinations of HTML, CSS and JavaScript. JSF provides all the
standard components like labels, buttons, hyper links, text fields, list boxes, panels or data tables.
9
1.4 Renderers
Not all JSF components are responsible for their own rendering. JSF allows separate classes to
handle the rendering process. Those classes are called renderers. JSF provides a standard render
kit for its UIComponents. However, JSF supports the development of custom renderers as well.
Renderers create a visual representation for the client (encoding) and, when JSF receives a
response form the user, the renderer extracts the request parameters (decoding).
1.5 Validators
Validators are used to examine the correctness of the given input values. JSF handles validation in
three ways:
• at the UIComponent level
• via validator methods in backing beans
• in validator classes
UIComponents usually handle simple validation, such as whether a value is required or not.
Validator methods are useful when you need to validate one or more fields on a form (and you
don't need this validator for other components). External validators are useful for generic cases.
You can attach one or more validators to any input component.
1.7 Converters
Converters translate an object to a string for display and from an input string to a Java object.
Furthermore, they handle formatting and localization. JSF ships with converters for common types
like dates, boolean or numbers, but anybody can develop additional converters which are applied
internally during encoding and decoding.
1.9 Navigation
JSF provides an elegant navigation system. The navigation handler is responsible for deciding
which page to load depending on the outcome of an action method. Navigation rules define what
outcomes are understood and which page to load on what outcome. These rules are defined in the
JSF configuration file (faces-config.xml).
10
1.10 The JSF expression language
The main point of JSF expressions is to allow you to reference JavaBean methods, to read or
update bean properties, or to evaluate simple statements, without writing any Java code.
JSF expressions are used to associate UIComponent properties with backing beans, but you can
use them for logical and mathematical statements as well. They are evaluated at runtime.
JSF 1.2 uses the Unified Expression Language (EL), i.e. it uses the same expression language
as JSP 2.1. JSF 1.2 depends on the unified EL API (javax.el).
• The EL uses the number sign (#) to mark the beginning of an expression.
• EL expressions can be two way: they can retrieve a properties value or update it.
• EL expressions can also reference object methods.
Value Expressions:
• #{myBean.myProperty} returns the value of myProperty of the object myBean.
• #{myBean.myList[2]} returns the second element of (the list or array) myList of
myBean.
• #{myBean.myMap['key']} returns the object stored under the key 'key' of the map
myMap.
Method Expressions:
• #{myBean.myMethod} assigns the method myMethod of the bean myBean.
11
12
2 Easy Example: Hello World!
We start with an easy but complete example, where we learn to know all the key pieces which
belong to a JSF application.
2.1 Hello.jsp
1. <?xml version="1.0" encoding="UTF-8"?>
2. <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
3. xmlns:f="http://java.sun.com/jsf/core"
4. xmlns:h="http://java.sun.com/jsf/html" version="2.1">
5. <jsp:directive.page contentType="text/html"/>
6.
7. <html xmlns="http://www.w3.org/1999/xhtml">
8. <head>
9. <link href="styles.css" rel="stylesheet" type="text/css"/>
10. <title>Hello, world!</title>
11. </head>
12. <body>
13. <f:view>
14. <h:form id="main">
15. <h:outputText value="#{helloBean.helloText}"
16. styleClass="header"/>
17. <p>
18. <h:outputText value="Your Name: "/>
19. <h:inputText id="helloInput"
20. value="#{helloBean.name}"/>
21. </p>
22. <p>
23. <h:outputText value="Your Age: "/>
24. <h:inputText id="helloAge"
25. value="#{helloBean.age}"/>
26. </p>
27. <h:commandButton id="sayHello" value="Say Hello"
28. action="#{helloBean.sayHello}"/>
29. </h:form>
30. </f:view>
31. </body>
32. </html>
33.</jsp:root>
13
Lines 1 to 5: First, we declare the namespaces for the core JSF tag libraries. These provide
custom tags like text boxes, output labels and forms. Usually the prefixes „f“ and „h“ are used for
these namespaces.
The „h“ tag library elements usually render HTML elements, whereas the core tags are
independent of a particular render kit (like <f:view>, <f:validator>, <f:converter> and so on).
The jsp:directive is used to define the content type of the target HTML page.
Line 13: The <f:view> tag must enclose all other JSF related tags.
Line 14: The <h:form> tag represents an HtmlForm component, which is a container for other
components and is used for posting information back to the server. We can have more than one
HtmlForm on the same page, but all input controls must be nested within a <h:form> tag.
Line 15: The <h:outputText> tag creates an HtmlOutputText component, which displays read-only
text on the screen. The value attribute #{helloBean.helloText} specifies an JSF Expression
Language reference to the property helloText of the backing bean. JSF automatically
synchronizes the value of the outputText with the helloText property. JSF tags can use the
usual CSS-styles of HTML.
Lines 19: <h:inputText> creates a new HtmlInputText component that accepts text input. The
value attribute #{helloBean.name} references the property name of the backing bean.
14
2.2 HelloBean.java
package helloWorld;
The sayHello() method is called, whenever the „Say Hello“ button is pressed. It computes the new
helloText. Its return value can be used to define the next page (navigation).
15
2.3 faces-config.xml
<?xml version='1.0' encoding='UTF-8'?>
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
version="1.2">
<managed-bean>
<description>The HelloBean.</description>
<managed-bean-name>helloBean</managed-bean-name>
<managed-bean-class>helloWorld.HelloBean </managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
</faces-config>
In the faces-config.xml file we declare all of the managed beans. Those are automatically
instantiated. Here the only managed bean is helloWorld.HelloBean. The name of the bean object is
helloBean. This name is also used in the EL expressions in hello.jsp (e.g. #{helloBean.name}).
It is good practice to choose similar names for the bean class and its object.
2.4 web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Hello, World!</display-name>
<description>Welcome to JavaServer Faces</description>
<!-- Faces Servlet : Front Controller -->
<servlet>
<servlet-name>FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<!-- Faces Servlet Mapping -->
<servlet-mapping>
<servlet-name>FacesServlet</servlet-name>
<url-pattern>/faces/*</url-pattern>
</servlet-mapping>
<!-- Welcome File -->
<welcome-file-list>
<welcome-file>faces/hello.jsp</welcome-file>
</welcome-file-list>
<!-- jsp pages are xml documents -->
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<is-xml>true</is-xml>
</jsp-property-group>
</jsp-config>
</web-app>
All J2EE web applications are configured by a deployment descriptor file (web.xml). Furthermore,
JSF applications require that you specify the FacesServlet, which is the main servlet (front
controller) of the application. All JSF requests are mapped to the FacesServlet.
16
3 JSF Application Configuration
3.1 The Directory Structure
<?xml version="1.0"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
<display-name>Display Name used by GUI Tools</display-name>
<description>Description of the Web application </description>
<!-- Configuration of faces-config file(s) (comma separated) -->
<context-param>
<param-name>javax.faces.CONFIG_FILES</param-name>
<param-value>/WEB-INF/faces-config.xml</param-value>
</context-param>
<!-- FacesServlet configuration and mapping -->
<servlet>
<servlet-name>Name of the Front Controller for your JSF Application,
usually FacesServlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Name of the Front Controller (the same as
above!)</servlet-name>
<url-pattern>path/*</url-pattern>
</servlet-mapping>
<!-- Welcome File -->
<welcome-file-list>
<welcome-file>path/firstPage.jsp</welcome-file>
</welcome-file-list>
17
<!-- all pages ending with .jsp are xml docs -->
<jsp-config>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<is-xml>true</is-xml>
</jsp-property-group>
</jsp-config>
</web-app>
18
The component, render-kit, validator and converter elements are used to declare custom
components, custom renderers, custom validators and custom converters (cf. Chapter 7).
The life cycle element allows you to register one or more phase listeners, which are executed before
or after each phase of the Request Processing Life cycle (cf. Chapter 6).
The factory element provides a mechanism to define custom Factories like a custom Application- or
FacesContextFactory.
The managed-bean element is used to configure a managed bean, which will be created and
initialized by the Managed Bean Creation Facility the first time it is requested by a JSF EL
expression. Every managed bean must be declared in a separate entry.
The managed-bean element has a subelement named managed-property which can be used to
initialize any read/write properties (Setter Injection pattern).
The following figure shows the full hierarchy of the managed bean element. <description>,
<display-name>, <icon>, ... are optional elements, generally used for tools.
19
The managed property element can even be used to assign a reference to a previously defined
managed bean. You must be careful about the scope of these objects, because a managed bean
can’t reference an object with a shorter life span than the managed bean itself. For an example of
a bean reference confer to the faces-config.xml of the next chapter.
Web applications usually have multiple pages, and we must have some way to move between
them. For any given page, a navigation-rule defines what outcomes are understood, and what
pages to load based on those outcomes. Each specific mapping between an outcome and a page
is a navigation-case.
<navigation-rule>
<description>description of navigation cases</description>
<from-view-id>fromPage</from-view-id>
<navigation-case>
<from-action>action</from-action>
<from-outcome>a return value of the action</from-outcome>
<to-view-id>toPage</to-view-id>
</navigation-case>
<navigation-case>
<from-action>action</from-action>
<from-outcome>other return value of the action</from-outcome>
<to-view-id>toPage</to-view-id>
</navigation-case>
. . . (other navigation cases for this page)
</navigation-rule>
The from-action element can be left out, which means that the outcome may be produced by an
arbitrary action method or even be a constant value.
The fromPage value can also be an asterisk ( * ), which means that this rule applies to all pages.
The same result is achieved by omitting the <from-view-id> element.
<description>, <display-name> and <icon> elements are optional and are generally used for tools.
The next chapter shows a full example of a managed bean with initial values for (some of) its
properties and different navigation rules.
20
3.4 Configuration and Navigation Example
We extend our first easy example by introducing two new features: navigation rules and managed
properties. The hello.jsp page obtains two more buttons (Details / Goodbye). By pressing the
Details button, the user loads the persons detail page, the Goodbye button leads to the goodbye
page.
3.5 Hello.jsp
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html" version="2.1">
<jsp:directive.page contentType="text/html"/>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href="styles.css" rel="stylesheet" type="text/css"/>
<title>Hello, world!</title>
</head>
<body>
<f:view>
<h:form>
<h:outputText value="#{helloBean.helloText}"
styleClass="header"/>
<p>
<h:panelGrid columns="2" cellpadding="3">
<h:outputText value="Your Name:"/>
<h:outputText value="#{personDetails.name}"/>
<h:outputText value="Your Age:"/>
<h:outputText id="helloAge" value="#{personDetails.age}"/>
</h:panelGrid>
</p>
<h:commandButton value="Say Hello"
action="#{helloBean.sayHello}"/>
<h:commandButton value="Details" action="details"/>
<h:commandButton value="Goodbye"
action="#{helloBean.sayGoodbye}"/>
</h:form>
</f:view>
</body>
</html>
</jsp:root>
When we load the hello.jsp page for the first time, the outputText fields for name and age get their
values from the personDetails backing bean. The default values for name and age in the backing
bean are set by the Managed Bean Creation facility (managed-property in the faces
configuration file) at creation time (cf. faces-config.xml below).
21
3.6 PersonDetails.jsp
The PersonDetails page can be used to change the properties for
name, age and the favorite numbers of the given person.
The favorite numbers are saved in an array or vector of integers in
the person details backing bean.
All of these properties read their initial value at creation time from
the faces-config.xml file.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href="styles.css" rel="stylesheet"
type="text/css"/>
<title>Person Details</title>
</head>
<body>
<f:view>
<h:form>
<h:outputText value="Person Details" styleClass="header"/>
<p>
<h:panelGrid columns="2" cellpadding="3">
<h:outputText value="Your Name:"/>
<h:inputText value="#{personDetails.name}"/>
<h:outputText value="Your Age:"/>
<h:inputText id="helloAge" value="#{personDetails.age}" size="4"/>
</h:panelGrid>
</p>
<p>
<h:outputText value="Enter your favorite Numbers:"/>
<h:panelGrid columns="3" cellpadding="3">
<h:inputText
value="#{personDetails.favoriteNumbers[0]}" size="4"/>
<h:inputText
value="#{personDetails.favoriteNumbers[1]}" size="4"/>
<h:inputText
value="#{personDetails.favoriteNumbers[2]}" size="4"/>
</h:panelGrid>
</p>
The panelGrid components above is used to align the two input text fields for name and age. The
back button leads back to the hello page.
22
3.7 Goodbye.jsp
The goodbye.jsp page doesn't need a backing bean for its own, as it only prints out the goodbye
helloText.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link href="styles.css" rel="stylesheet"
type="text/css"/>
<title>Hello, world! </title>
</head>
<body>
<f:view>
<h:form>
<h:outputText value="#{helloBean.helloText}"
styleClass="header"/>
</h:form>
</f:view>
</body>
</html>
</jsp:root>
3.8 faces-config.xml
The Managed Bean Creation Facility uses the <managed-bean> element to create an instance
of helloWorld.PersonDetails and and store it in the session under the name personDetails
the first time the bean is accessed. As long as the same session is in use, the same instance of
personDetails will be used. This instance can be referenced with the expression #{personDetails}
(or #{sessionScope.personDetails }).
The same holds for the helloWorld.helloBean backing bean.
The properties are initialized with <managed-property> elements. The <value> element contains
the default value of the property specified in the <property-name> element. The Bean Creation
facility uses the associated setter method to assign the initial values to the right properties
(Property Injection: cf. Setter Injection pattern).
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd"
version="1.2">
23
<managed-bean>
<description>Detail Information of a person</description>
<managed-bean-name>personDetails</managed-bean-name>
<managed-bean-class>helloWorld.PersonDetails</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>name</property-name>
<value>John</value>
</managed-property>
<managed-property>
<property-name>age</property-name>
<value>17</value>
</managed-property>
<managed-property>
<property-name>favoriteNumbers</property-name>
<property-class>java.util.Vector</property-class>
<list-entries>
<value-class>java.lang.Integer</value-class>
<value>3</value>
<value>17</value>
<value>347</value>
</list-entries>
</managed-property>
</managed-bean>
<managed-bean>
<managed-bean-name>helloBean</managed-bean-name>
<managed-bean-class>helloWorld.HelloBean </managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>personDetails</property-name>
<value>#{personDetails}</value>
</managed-property>
<managed-property>
<property-name>helloText</property-name>
<value>Hello World!</value>
</managed-property>
</managed-bean>
To print out the name and the age of the given person, the helloBean backing bean needs a
reference to the personDetails backing bean. The reference to the previously defined managed
bean (PersonDatails) can be assigned to the helloBean via a normal JSF EL expression
(Dependency Injection).
24
3.9 Navigation
In the faces configuration file, we find three navigation cases for hello.jsp and one for the
personDetails.jsp page:
• By pressing the „Say Hello“ button, the sayHello action is processed which produces the
outcome „hello“. Therefore the hello.jsp page will be reloaded (with the new values entered
by the user).
• Pressing the „Details“ button leads us to the personDetails.jsp page.
• Pressing the „Goodbye“ button executes the sayGoodbye action method which produces
the outcome „goodbye“, which leads us to the goodbye.jsp page.
• From the personDetails page we can go back to the hello.jsp page by pressing the „Back“
button.
<navigation-rule>
<description>Navigation from the Person Details page.</description>
<from-view-id>/details.jsp</from-view-id>
<navigation-case>
<from-outcome>back</from-outcome>
<to-view-id>/hello.jsp</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
25
3.10 HelloBean.java
The helloBean.java file has a new action method for the Goodbye button: sayGoodbye():
package helloWorld;
26
4 The Standard JSF Components
In this chapter, we cover the standard components that all JSF implementations must support.
They provide the basic set of functionality necessary for building HTML-based web applications.
You can expect third-party developers to provide additional components as well. Here we will focus
on the most important components only.
We start with the basic attributes, which are applicable to most of the components.
• id: An identifier for a component
• rendered: A boolean value, if set to false suppresses rendering of this component
• value: The components value, typically a value binding
• required: A boolean value, if true a value is required for this input field
• styleClass The CSS class name which should be used for this component
The HtmlPanelGroup component groups a set of components together, so that they can be
treated as a single entity.
27
4.2 The Output Components
The purpose of the output components is to display data. You can specify literally the data that
they display or have them display properties from backing beans.
The most basic output component is HtmlOutputText (<h:outputText>). HtmlOutputText converts
the given value to a string and displays it with optional CSS style support.
Example:
<h:outputText value="#{helloBean.helloText}" styleClass="header"/>
<h:outputText value="#{helloBean.goodbyeText}" styleClass="header"/>
The HtmlOutputLabel component is used for associating labels with form elements (InputText,
ChoiceButton, ...). HtmlOutputLabel is translated to the HTML <label> element. This allows target
devices to define shortcuts for input elements.
Example
<h:panelGroup>
<h:outputLabel for="helloInput" accesskey="N">
<h:outputText value="Your Name:"/>
</h:outputLabel>
<h:inputText id="helloInput" value="#{helloBean.name}"
required="true" accesskey="N"/>
</h:panelGroup>
The HtmlInputText component is used for basic user input. It maps to a simple text field—the
<input> element with type “text”.
The size and disabled properties are passed through to the HTML input tag. In this example, the
component is associated via a value-binding expression with the name property of helloBean.
HtmlInputText is the most common input control, but it is
restricted to a single line.
If you need a multi line input field, you can use the
HtmlInputTextarea component.
<h:inputTextarea value="#{helloBean.helloText}" rows="5" />
28
The HtmlInputSecret component is used to display a password input field. Any text the user types
is displayed using the asterisk or some other character (depending on the browser).
The selectBooleanCheckbox component works fine for a single check box on a form. If you want to
associate multiple check boxes with a single property, you preferably use a HtmlSelectMany-
Checkbox (see next chapter).
A UISelectItem component are used to display items in a list and to select one or more items from
this list. You can either use the value itemDescription, itemLabel, and itemValue properties or a
value-binding expression.
Alternatively, you can use a selectItems tag with a value binding to a list or array of elements.
<f:selectItems value="#{myBean.animalList}"/>
These selectItem(s) tag can be used to configure another component’s selection list (e.g. for
components like HtmlSelectManyCheckbox, HtmlSelectOneRadio, HtmlSelectOneListbox or
HtmlSelectOneMenu).
All of these choice components work in a similar way. Therefore, only one of these components is
described here: HtmlSelectOneMenu.
HtmlSelectOneMenu displays its child items in a list box using the HTML <select> element. The
number of items displayed is always one, so the result is a combo box (also called a drop-down list
box).
29
<h:outputText value="Your Favorite Animal "/>
<h:selectOneMenu id="animal" value="#{helloBean.animal}" accesskey="A">
<f:selectItems value="#{helloBean.animals}"/>
</h:selectOneMenu>
<managed-bean>
<description>The one and only HelloBean.</description>
<managed-bean-name>helloBean</managed-bean-name>
<managed-bean-class>helloWorld.HelloBean </managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
<managed-property>
<property-name>animals</property-name>
<list-entries>
<value>Cat</value>
<value>Dog</value>
<value>Bird</value>
</list-entries>
</managed-property>
</managed-bean>
In the backing bean, you have to provide the corresponding get and set methods for the favorite
animal and the selection list of animals:
30
4.5 Data Tables
The HtmlDataTable component displays an HTML <table>. The columns are specified with
column components. For each row, HtmlDataTable uses the column components as a
template for each column. If the facet tag has a name=“header“ attribute, it is translated to a
<thead> (table header) HTML tag. The var property defines the name of the iterator
variable (here person). If the row property
is specified, it displays that many rows
(starting with the first).
In the backing bean, you have to provide a corresponding list of friends (here Person) with a
firstName, a lastName and an age attribute.
31
public String getFirstName(){
return firstName;
}
public void setFirstName(String firstName){
this.firstName = firstName;
}
The table looks similar to the previous one, but there are some important differences. The Last-
Name column uses an <h:commandLink> component instead of an outputText and the value of the
<h:dataTable> is now an instance of javax.faces.model.DataModel instead of the previous array of
Person.
How can we determine which row of the table has been selected when handling the action event?
You could find it out by using a query string parameter or a hidden field.
However, JSF offers a much easier way to represent tabular data through the abstract DataModel
class. DataModel has two subclasses: ListDataModel and ArrayDataModel. These are
convenience implementations of the abstract DataModel class with the following properties:
32
• boolean: rowAvailable is true, when the rowIndex property holds the index of an
existing row, false otherwise.
• int: rowCount is the number of rows (or -1 if unknown)
• Object: rowData the object at rowIndex (or null if rowIndex = -1)
• int: rowIndex gives the currently selected row (or -1, if no row is selected)
• Object: wrappedData is the object representing the table.
The <h:dataTable> uses the personModel DataModel to read the table entries from. There are
no changes necessary in the HelloBean or Person class. All we need is a new PersonHandler
class as a wrapper for the array of Person objects.
package helloWorld;
import javax.faces.model.*;
The <h:commandLink> in each table row is bound to the PersonHandlers select() method. The
renderer together with the UIData component ensure that the DataModels rowIndex is
positioned to the selected row when the action method is invoked. Therefore, we can use
getRowData() in the select() method to read the data of the selected person.
33
4.7 The Command Components
The command components represent an action initiated by the user. The two standard command
components are HtmlCommandButton (for displaying a button) and HtmlCommandLink (for
displaying a hyper link). Because they perform the same operation, their usage is quite similar.
34
5 Messaging
5.1 Messages
Multiple parts of a JSF application (validators, converters, application exceptions ... ) can generate
messages. Usually, these messages have to be displayed to the user.
The attributes showDetail and showSummary are optional. The default value for showDetail is true,
that for showSummary is false.
Every message has a severity level which is equal to one of the following values.
• Info - Represents an informational text to be send back to the user. You can insert an
infoClass or an infoStyle attribute to define a CSS class / CSS style for messages
with Info severity.
• Warn - Indicates that an error may have occurred.You can insert a warnClass or a
warnStyle attribute to define a CSS class / CSS style for messages with Warn severity.
• Error - Indicates an error like validation or conversion error. You can insert an
errorClass or an errorStyle attribute to define a CSS class / CSS style for messages
with error severity.
• Fatal - Indicates a serious (application) error. You can insert an fatalClass or a
fatalStyle attribute to define a CSS class / CSS style for messages with fatal severity.
Whenever possible, the error is placed next to the component (so the user knows where the
problem arises). If more than one message is registered for a component (which can happen if
more than one validator is registered, or if a validator has problems with conversion), HtmlMessage
displays only the first one.
If you need to display multiple messages for a page, you should use HtmlMessages instead.
35
5.2 Overriding standard Messages
All of the standard validators and converters have default messages. These are configured using a
normal Java message bundle. In the reference implementation, for example, we would find the
following key/value pair, creating a message for an empty input field with a required=“true“
attribute:
The used parameters are defined in the JSF documentation for the corresponding messages.
In general, these default messages are not very user friendly. Therefore we often would like to
override these texts with custom messages. One possibility is to define an error message in the
tag of the corresponding input component. Possible values are
– requiredMessage for required input,
– converterMessage for conversion errors and
– validatorMessage for validation errors.
Furthermore, the details message texts are often missing. We can override the default messages
by a custom message bundle. Each JSF application can be associated with a single message
bundle (e.g. messages.properties), which is configured in the faces-config.xml file:
<faces-config>
<application> <!-- messages.properties file at /WEB-INF/classes -->
<message-bundle>messages</message-bundle>
</application>
. . .
</faces-config>
Once, you have defined a message bundle, you can selectively override the standard messages,
as long as you use the correct keys (see java.sun.com/javaee/javaserverfaces/
1.2_MR1/docs/api/index.html for the list of message keys).
Whenever a JSF component, validator or converter looks for an error message, it will look for them
in the JSP page and in the custom messages bundle (messages.properties). Only if there is no
user defined message, it will take the predefined standard message.
36
5.3 Constructing Application Messages
Whenever one of your backing beans throws an exception or when an error occurs in your
application logic (e.g. system or connection errors), you want to inform the users about this.
For this, you can create a message in your backing bean (or validator or converter class or
method).
if (!isValidName(name)) {
You have to add this messages to the FacesContext, from where the JSP page will read it
afterwards: context.addMessage(null,message));
The addMessage function takes two parameters: the message id (either the component id or null, if
the message does not belong to any component) and the FacesMessage.
Application messages do not belong to any component on the jsp page. If we want to retrieve the
application messages only (the messages, which belong to no component) we use the
globalOnly attribute:
<h:messages globalOnly=“true“>.
37
Retrieving Message Texts from the Message Bundle
In the previous example, we used hard coded message texts from our backing beans. Usually, you
want to read those messages from a message bundle, instead. Therefore, you preferably use the
custom message bundle to define your application messages and read these message texts from
there.
In the following example we take this improved approach. In your backing bean, you create a
message (of type FacesMessage) by first extracting the name of the message bundle and from this
the summary and detail string of the desired message.
38
Example: Print out an information message for invalid name values (cf. HelloWorld4).
helloBean.java
/** Define the text to say hello. */
public String sayHello() {
FacesContext context = FacesContext.getCurrentInstance();
if (!isValidName(name)) {
helloText = "Hello!";
} else {
if (age < 10)
helloText = "Hello " + name + "!";
else
helloText = "Good Morning " + name + "!";
}
return "hello";
}
The messages.properties file for the application message contains messages of the form:
javax.faces.component.UIInput.REQUIRED= This value is required.
javax.faces.component.UIInput.REQUIRED_detail={0}: Input value must not be void.
javax.faces.converter.IntegerConverter.INTEGER=The given input value ''{0}'' is
not an integer.
javax.faces.converter.IntegerConverter.INTEGER_detail={2}: The input value
should be an integer like 17.
hello.jsp
<h:form id="main">
<h:outputText value="#{helloBean.helloText}" styleClass="header"/>
<h:panelGrid columns="3">
<h:outputText value="Your Name"/>
<h:inputText id="name" label="Name" value="#{helloBean.name}"
required="true" requiredMessage="Please enter your name"/>
<h:message for="name" errorClass="errorStyle"
showDetail="false" showSummary="true"/>
39
<h:outputText value="Your Age"/>
<h:inputText id="age" label="Age" value="#{helloBean.age}"
required="true"/>
<h:message for="age" errorClass="errorStyle" showDetail="false"
showSummary="true"/>
<h:outputText value="Country"/>
<h:inputText id="country" label="Country"
value="#{helloBean.country}" required="true"/>
<h:message for="country" errorClass="errorStyle" showDetail="false"
showSummary="true"/>
</h:panelGrid>
We then obtain either one or more error messages (in case of any input errors):
40
6 Request Processing
When a JSF view is requested, the components in the view are asked to perform tasks in a certain
order, defined as phases of a request processing life cycle. The following graphic shows the main
tasks for each phase.
41
6.2 Apply Request Values
• Decoding: extract all user input from the input fields (and save them in the submittedValue
attribute of the component).
• Create action events and add them to the faces context for later processing.
• If the immediate attribute of a component is set to true, validation takes place in this phase
instead of the process validation phase.
• If there is a command button or a hyper link with an immediate property set to true, the
corresponding actions will be fired in this phase instead of the invoke application phase. This
can be used for example for Cancel buttons, because it prevents the validation of any input
fields.
6.3 Process Validation
• Convert submitted values: Convert the value of the submittedValue attribute of the
component from string type to object.
• Validate submitted values: After conversion, the value is validated and set as the local value
of this component.
• If the conversion or the validation process throws an exception, the control will skip to the
render response phase (6).
• If the local value has changed, a valueChangeEvent is fired and consumed by the registered
listeners.
42
7 Validators and Converters
JSF supports validation and conversion through validator or conversion methods of backing beans
and validator and converter objects.
Validation checks the value of a control to see if its current value is acceptable. The associated
object in the backing bean is updated only if the value is accepted. Otherwise, an error message is
generated for that specific component, and the associated object is not modified. These
error messages can then be displayed back to users with a <h:message> or <h:messages> tag.
When users see an object on the screen, they see it in terms of recognizable text, like May 23,
1980. A Java Date object, on the other hand, is much more than just a string. Two Date objects
can be compared and we can compute the elapsed time between the two dates.
This is the purpose of a converter - to create a string representation of an object, and to create an
object representation of a string.
JSF provides a set of standard converters to satisfy the basic type conversion needs. You can
also write your own converters, and third-party vendors will provide them as well.
As with validators, converters create converter exceptions and send them back to the user as
faces messages.
<f:validateLength> can be used to ensure that the number of letters given in the input field is
greater/smaller than or equal to the specified minimum/maximum value.
43
7.2 Validator Methods
An input field can also be associated with a validation method on a backing bean. Validation
methods are generally used for application specific validation and can not be reused for different
applications. For any input component you can register one or more validators.
To ensure that this validator class is instantiated, we have to declare it as validator in the faces-
config.xml file:
44
<faces-config>
<managed-bean>
. . .
</managed-bean>
<navigation-rule>
. . .
</navigation-rule>
<validator>
<validator-id>NameValidator</validator-id>
<validator-class>helloWorld.NameValidator</validator-class>
</validator>
</faces-config>
<h:inputText value="#{helloBean.dateOfBirth}">
<f:convertDateTime type="date"/>
</h:inputText>
f:convertDateTime can be used to convert a Date object to a string (and vice versa). The type
attribute is optional and can be either date or time or both, depending on what you want to print
out.
The number converter is useful for displaying numbers in basic formats like a currency or a
percentage.
<h:inputText value="#{helloBean.price}">
<f:convertNumber pattern="SFr. #,##0.00"/>
</h:inputText>
45
7.6 Using Custom Converters
In many cases, the standard converters will be sufficient; they handle all of the standard Java data
types, and also provide sophisticated formatting functionality for dates and numbers.
You have to develop custom converters any time you want to make it easy for a front-end
developer to display a special data type, or accept input for that special data type.
In our example, the user can insert a two letter country code, which is automatically converted into
the corresponding country name.
<converter>
<converter-id>CountryConverter</converter-id>
<converter-class>helloWorld.CountryConverter
</converter-class>
</converter>
46
8 Internationalization
Enabling an application to support multiple locales is called internationalization. The process of
modifying an application to support a (new) locale is called localization. Some implementations,
like the reference implementation, provide localized messages for validator and converter errors for
certain languages (English, French and German).
<faces-config . . . >
<application>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>de</supported-locale>
</locale-config>
<message-bundle>messages</message-bundle>
<resource-bundle>
<base-name>texts</base-name>
<var>label</var>
</resource-bundle>
</application>
If the bundles are placed in WEB-INF/classes, no prefix is needed. However, if we had nested
them deeper, like in the WEB-INF/classes/org/jia directory, the basename would be “org.jia.texts”.
Once the bundle has been loaded, you can grab a particular string from that bundle with an
ordinary value-binding expression such as #{label.theKey}.
If the resource bundle can not find a key, it will return the string “??? key ???” instead.
With JSF 1.1 you had to define the texts with the <f:loadBundle> tag. The following tag loads the
bundle and stores it in the request scope.
<f:view>
The basename attribute specifies the name of the resource bundle, prefixed by its location in your
classpath. The var attribute specifies the name which is used in your JSF component tags. Both
attributes (basename and var) are required.
47
8.2 Configuring Locales
The first step towards supporting multiple languages is to tell your JSF application which locales it
should support and which of the supported locales should be used as the default locale. You
specify the supported locales with the <locale-config> element in the faces configuration file:
<faces-config>
<application>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>de</supported-locale>
<supported-locale>fr</supported-locale>
<supported-locale>it</supported-locale>
</locale-config>
</application>
...
</faces-config>
Resource bundles are not a JSF feature—they are a fundamental part of the way Java handles
internationalization and localization. Resource bundles are normal property files with key/value
pairs. Each string has a key, which is the same for all locales. So the key „helloWorld“ points to the
string that represents the welcome message, whether it is in English, French, or German.
texts_de.properties
helloWorld=Hallo, ihr alle!
yourName=Ihr Name
dateOfBirth=Geburtsdatum
country=Land
hello=Hallo
goodMorning=Guten Tag
goodbye=Auf Wiedersehen
seeYou=Tschüss
texts_en.properties
helloWorld=Hello, world!
yourName=Your Name
dateOfBirth=Date of Birth
country=Country
hello=Hello
goodMorning=Good Morning
goodbye=Goodbye
seeYou=See you
48
8.4 Using Resource Bundles
Once you have created one or more resource bundles, you will have to make sure that your JSF
components use the string in the bundle instead of a hard coded text value:
<h:outputText value="#{label.yourName}"/>
<h:outputText value="#{label.dateOfBirth}"/>
<h:commandButton value="#{label.goodbye}"
action="#{helloBean.sayHello}"/>
If you need localized texts in your backing beans, a getText method like the following can be
useful:
private String getText(String key) {
String text = "???" + key + "???";
try {
FacesContext context = FacesContext.getCurrentInstance();
Locale locale = context.getViewRoot().getLocale();
ResourceBundle bundle = ResourceBundle.getBundle("texts", locale);
text = bundle.getString(key);
}
catch (MissingResourceException e) {}
return text;
}
You can use this method to extract the correct string from the bundle:
helloText = getText("goodbye") + " " + name + "!";
<faces-config>
<application>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>en</supported-locale>
<supported-locale>de</supported-locale>
</locale-config>
<message-bundle>messages</message-bundle>
</application>
...
</faces-config>
49
For each of the supported locales, you have to provide a corresponding messages_xx.properties
file:
messages_de.properties (German message bundle)
javax.faces.validator.LengthValidator.MAXIMUM=Die Eingabe ist zu lang.
javax.faces.validator.LengthValidator.MAXIMUM_detail=Der Eingabewert darf
höchstens {0} Zeichen lang sein.
javax.faces.validator.LengthValidator.MINIMUM=Die Eingabe ist zu kurz.
javax.faces.validator.LengthValidator.MINIMUM_detail=Der Eingabewert muss
mindestens {0} Zeichen lang sein.
NameValidator.INVALID_NAME=Ungültiger Namenswert.
NameValidator.INVALID_NAME_detail=Namenswert entspricht nicht dem Pattern [A-Z]
[a-z]*
CountryConverter.INVALID_COUNTRY_KEY=Ungültiger Ländercode.
CountryConverter.INVALID_COUNTRY_KEY_detail=Land muss ein Ländercode aus 2
Buchstaben sein
JSF will use your bundles to override default validation and conversion error messages.
50
8.6 Using Localized Message Bundles for Application Messages
You can also use the message bundle to create your own (error) messages.
In your backing bean, validator or converter, you can create a message (of type FacesMessage)
by first extracting the client's locale, the name of the message bundle and from this the summary
and detail string of the dedicated message. The FacesMessage constructor takes the arguments
severity (SEVERITY_INFO, SEVERITY_WARN, SEVERITY_ERROR, or SEVERITY_FATAL)
summary string and detail string.
The MessageFactory from chapter has to be changed somewhat to provide us with the desired
localized FacesMessage:
MessageFactory.java
public class MessageFactory {
We can use this MessageFactory in any backing bean, custom converter or custom validator, to
create localized error messages:
51
52
9 Custom Tags
As we’ve already seen, JavaServer Faces has several services that enable you to build web
applications quickly. Many standard components are available already, and different IDE vendors
provide many additional components.
However, the real power of JSF lies in its sophisticated component model and an extensible
architecture that allows you to create your own user interface (UI) extensions—components,
renderers, validators, and converters.
In this chapter we learn how to create our own custom tags.
Before you write a new custom tag or custom component, you should make sure that there is no
alternative way you can reach your goal: you can visit the JSF Central page (www.jsfcentral.com),
for example, to find out about different JSF products and libraries.
With custom tags for validators or converters we are able to provide custom tag attributes. These
attributes are used as custom properties (e.g. a regular expression used by a custom validator to
match certain input strings <g:validateRegex pattern="[a-z]{5}"/>).
Custom tags for validators and converters are implemented in the same way. The following
sections show all the details needed to implement a custom validator tag.
53
The Validator Tag Class
The validator tag class has to extend the abstract ValidatorELTag class, which means it has to
implement a createValidator() method. Furthermore, the validator tag class needs setter methods
for all attributes of the tag. If the custom tag provides any attributes, the tag class should
implement a release() method.
public class MyValidatorTag extends ValidatorELTag {
54
The Tag Library Description File
For the JSP integration we need a Tag-Library description of the new tag (customValidator.tld):
<taglib . . . >
<tlib-version>1.0</tlib-version>
<short-name> ns-Prefix </short-name>
<uri> tag_URI </uri>
<tag>
<name> tag_name </name>
<tag-class> tag_class_name </tag-class>
<body-content> normally empty</body-content>
<attribute>
<description> . . . </description>
<name>attribute name</name>
<required>true | false</required>
<deferred-value>
<type>type of attribute</type>
</deferred-value>
</attribute>
</tag>
. . .
<taglib>
// getter and setter methods for all properties and transient value
. . .
}
55
In the faces-config.xml file we have to register all custom validators by their id and fully qualified
class name:
<validator>
<validator-id>CustomValidatorId</validator-id>
<validator-class>package.CustomValidatorClass</validator-class>
</validator>
Configuration Summary
56
9.2 The Greater-Than Validator
57
// value holder method
public void restoreState(FacesContext fc, Object state) {
compareToId = (String) state;
}
58
The GreaterThanValidatorTag Class
The ValidatorTag class must implement the createValidator() method as well as a setter
method for its properties (compareToId) and a release method.
59
<taglib version="2.1"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-jsptaglibrary_2_1.xsd">
<tlib-version>1.0</tlib-version>
<short-name>myTags</short-name>
<uri>http://helloWorld/taglib</uri>
<tag>
<name>validateGreaterThan</name>
<tag-class>helloWorld.GreaterThanValidatorTag</tag-class>
<body-content>empty</body-content>
<attribute>
<description>Id of component this field is compared to</description>
<name>compareToId</name>
<required>true</required>
<deferred-value>
<type>java.lang.String</type>
</deferred-value>
</attribute>
</tag>
. . .
</taglib>
The custom tag can then be used in the JSP page like this:
<jsp:root version="2.1" xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:g="http://helloWorld/taglib">
....
<f:view>
<h:form id="main">
....
<h:outputText value="#{label.yourAge}" />
<h:inputText id="age" label="#{label.yourAge}"
value="#{helloBean.age}" required="true" />
<h:message for="age" styleClass="errorMessage" />
60
and the extensible architecture allow to create new components. But the development of custom
components requires special expertise.
encodeBegin()
encodeChildren()
encodeEnd()
saveState()
restoreState()
The put() and get() methods of the attributes indirectly access the properties and value
expressions if available. If a component defines properties, it must implement the StateHolder
interface to save and restore them.
61
10.3 Value Holder
The ValueHolder interfaces support a component's values which are used during request
processing:
• a submitted value which is the value entered by a user and decoded from the request
• a local value which is the value after successful processing by any registered converter and
validators
• a backing bean property to which the local value is transferred through a value expression
The getValue() method either returns the submitted value, the local value or the value of the
associated backing bean property
PROCESS VALIDATIONS
APPLY REQUEST VALUES 2: validate()
1: decode() 2a: setValue()
1a: setSubmittedValue() 2b: clearSubmittedValue()
3b: setProperty()
Input Backing
Component Bean
5c: getProperty()
62
10.4 Example of a Custom Component
UIComponent UIComponent
Base ELTag
registers registers
JSF Tag
Configu- Library
ration Descriptor
In this example a custom input component is developed which allows a user to select a number
within a range of numbers. The custom component may be included in a JSP page using a custom
tag which specifies the range of numbers and a value binding for the selected number:
<h:form>
...
<h:outputText value="#{label.age}" />
<g:selectNumber id="helloAge" min="1" max="50" value="#{helloBean.age}" />
...
<h:commandButton value="#{label.hello}" action="#{helloBean.sayHello}" />
</h:from>
63
The Component Class: SelectNumber
64
The Configuration File: faces-config.xml
In the application configuration file, the component has to be declared by specifying its type and its
implementation class
<managed-bean>
<description>The one and only HelloBean.</description>
<managed-bean-name>helloBean</managed-bean-name>
<managed-bean-class>helloWorld.HelloBean</managed-bean-class>
<managed-bean-scope>session</managed-bean-scope>
</managed-bean>
. . .
<component>
<component-type>SelectNumber</component-type>
<component-class>helloWorld.SelectNumber</component-class>
</component>
. . .
</faces-config>
The component tag handler class is derived from the UIComponentELTag class. The component
tag handler associates the tag with a component and with a renderer (if the component does not
render itself).
If the component has attributes or properties which should be exposed as tag attributes, the tag
handler class has to define corresponding properties (here min, max, and value). We need setter
methods as well as a release method for those properties.
The setProperties() method maps the properties of the tag class to attributes or value expressions
of the component
65
/** Returns the renderer type. */
public String getRendererType() {
return null;
}
66
The Tag Library Descriptor: taglib.tld
The tag library descriptor (TLD) groups different JSP tags into a tag library which is identified by a
URI. A tag description maps a tag name (here selectNumber) to a tag handler class (here
helloWorld.SelectNumberTag) and defines the valid tag attributes (max, min, value and id).
<?xml version="1.0"?>
<taglib . . . >
<tlib-version>1.1</tlib-version>
<short-name>myTags</short-name>
<uri>http://helloWorld/taglib</uri>
<tag>
<name>selectNumber</name>
<tag-class>helloWorld.SelectNumberTag</tag-class>
<body-content>empty</body-content>
<attribute> <name>id</name>
</attribute>
<attribute> <name>min</name> <required>true</required>
</attribute>
<attribute> <name>max</name> <required>true</required>
</attribute>
<attribute>
<name>value</name>
<required>true</required>
<deferred-value>
<type>java.lang.Integer</type>
</deferred-value>
</attribute>
</tag>
</taglib>
In the JSP page, the URI of the tag library has to be defined as XML namespace of the tag
element.
<jsp:directive.page contentType="text/html"/>
<html xmlns="http://www.w3.org/1999/xhtml">
<f:view>
<h:form>
<g:selectNumber min="1" max="10" value="#{helloBean.number}"/>
<h:commandButton value="Submit"/>
</h:form>
</f:view>
</html>
</jsp:root>
67
Packaging the Component
A custom UI component can be packaged together with the application's web archive or in a
separate JAR file which can then be included in an application's web archive
jsf-application.war jsf-component.jar
index.jsp /META-INF
... faces-config.xml
/WEB-INF taglib.tld
web.xml /jsf/examples
faces-config.xml SelectNumber.class
/WEB-INF/classes SelectNumberTag.class
...
/WEB-INF/lib
jsf-component.jar
68