Berner Fachhochschule

Software Schule Schweiz

JavaServer Faces
java.sun.com/javaee/javaserverfaces

Dr. Beatrice Amrhein

May 08

2

Table of Contents
1
1.1 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 1.10

Introduction ...............................................................................................................................5
JSF in Comparison to other Web Frameworks....................................................................................................5 The JSF Application Structure..............................................................................................................................8 The JSF Concepts................................................................................................................................................9 UIComponents.....................................................................................................................................................9 Renderers...........................................................................................................................................................10 Validators...........................................................................................................................................................10 Backing Beans...................................................................................................................................................10 Converters..........................................................................................................................................................10 Events and Event Listeners................................................................................................................................10 Navigation..........................................................................................................................................................10 The JSF expression language............................................................................................................................11

2
2.1 2.2 2.3 2.4

Easy Example: Hello World! ..................................................................................................13
Hello.jsp..............................................................................................................................................................13 HelloBean.java...................................................................................................................................................15 faces-config.xml.................................................................................................................................................16 web.xml..............................................................................................................................................................16

3
3.1 3.2 3.3 3.4 3.5 3.6 3.7 3.8 3.9 3.10

JSF Application Configuration .............................................................................................17
The Directory Structure......................................................................................................................................17 The Deployment Descriptor................................................................................................................................17 The JSF Configuration File.................................................................................................................................18 Configuration and Navigation Example..............................................................................................................21 Hello.jsp..............................................................................................................................................................21 PersonDetails.jsp...............................................................................................................................................22 Goodbye.jsp.......................................................................................................................................................23 faces-config.xml.................................................................................................................................................23 Navigation..........................................................................................................................................................25 HelloBean.java...................................................................................................................................................26

4
4.1 4.2 4.3 4.4 4.5 4.6 4.7

The Standard JSF Components ............................................................................................27
The Layout of the Components..........................................................................................................................27 The Output Components....................................................................................................................................28 The Basic Input Components.............................................................................................................................28 Choice Input Components..................................................................................................................................29 Data Tables........................................................................................................................................................31 Processing Row-Specific Events........................................................................................................................32 The Command Components..............................................................................................................................34

5
5.1 5.2 5.3

Messaging ...............................................................................................................................35
Messages...........................................................................................................................................................35 Overriding standard Messages..........................................................................................................................36 Constructing Application Messages...................................................................................................................37

6
6.1 6.2 6.3 6.4 6.5 6.6

Request Processing ...............................................................................................................41
Restore View .....................................................................................................................................................41 Apply Request Values .......................................................................................................................................42 Process Validation..............................................................................................................................................42 Update Model Values ........................................................................................................................................42 Invoke Application .............................................................................................................................................42 Render Response..............................................................................................................................................42

7
7.1 7.2 7.3 7.4 7.5 7.6

Validators and Converters .....................................................................................................43
Standard Validators............................................................................................................................................43 Validator Methods..............................................................................................................................................44 Validator Classes...............................................................................................................................................44 Automatic Conversion........................................................................................................................................45 Standard Converters..........................................................................................................................................45 Using Custom Converters..................................................................................................................................46

3

.............................................................................................2 Custom Tags .........1 8.48 Using Resource Bundles...........................................................6 Internationalization .................................................................................................................................4 8..................................49 Constructing Localized Messages ........................................1 10................................................48 Creating Resource Bundles.....51 9 9...5 8.................................................................61 Component Data Collections....................................................61 The Component Hierarchy.................................................................................................................................57 10 10.............2 8........3 10......................................................................................53 The Greater-Than Validator ...............8 8.....................................................................................................2 10..........................................................................................................47 Configuring Locales.........................................................................................................................................................................................................................................................63 4 .......................................3 8..............................................4 JSF Custom Components .....49 Using Localized Message Bundles for Application Messages .........62 Example of a Custom Component ..............................................................................................................................................................................................................47 Load the Resource Bundle...........................................................53 The different parts of a Custom Tag........................................61 Value Holder..................1 9......................................................................................................................................................................

Conversion and validation. Moreover. IBM WebSphere Application Developer. Because the JavaServer Faces technology architecture separates the definition of a component from its rendering. For example. JavaServer Faces technology already has wide industry support and is build in several web application development IDEs (Sun Java Studio Creator.1 Introduction 1. extensible UI component model. these components have no object representation on the server and they can only be rendered to an HTML client. In fact. As a result. you can render your components in different ways or even for different clients. or more complex ones. a component used for selecting an item from a list can be rendered as a menu or a set of radio buttons.myfaces. A separate rendering model that defines how to render the components in various ways. the extensible component APIs of JavaServer Faces technology allow you to extend the standard set of components and create entirely new components.. An event model that defines how to handle events generated by activating a component. such as input fields. While Struts does have a useful tag library for rendering components on the page.. which includes: • • • • A standard component API for a wide range of components. MyFaces. which also means that it has no event model for responding to component events and no facility for saving and restoring component state. . such as what to do when a user clicks a button or a hyper link.g. error handling.) Web Frameworks JSF Struts JSP Servlets Web server 3 HTTP request / response Like the Struts framework. http://www. and many third parties have already done so and have made their component libraries publicly available (e. Oracle JDeveloper). Developers can also create their own components based on the JSF APIs.1 JSF in Comparison to other Web Frameworks Automatic markup generation Declarative integration of backing beans UI component model Server side handling of UI events Type conversion Navigation Form handling and validation Extensible templating mechanism Integration with Java (session management. such as a WML client. Another distinct advantage of JavaServer Faces technology is that it has been designed to allow easy integration into tools. The greatest advantage that JSF technology has over Struts is its flexible.org/). None of this is possible with Struts. including simple ones. such as scrollable data tables. 5 . JSF defines a set of JSP tags that generate HTML form elements that can be bound to JavaBean properties. Struts has no notion of server-side components.

JSF is also responsible for making sure that every UIComponent you have used on your pages is properly displayed on your browser. it causes a request to be sent from your web browser to the server. JSF applications run on the server and can integrate with other subsystems like EJBs. the used backing beans and so on. 6 . 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).Web browsers don't know anything about JSF components or events. web services or databases. faces-config. or more precisely to the FacesServlet. When a user clicks a button in a JSF application. we define the navigation rules.xml is the central configuration file for JSF applications. Here.

com/jsf/html" version="2. These pages can also be designed by an IDE like Sun Java Studio Creator.0" encoding="UTF-8"?> <html><head><title>Hello. a JSF page looks similar to a normal HTML or JSP page.sun.sun.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. At runtime.jsp" enctype="application/x-www-form-urlencoded"> <input type="hidden" name="main" value="main" /> <input type="hidden" id="javax. 7 . the generated HTML page looks as follows: <?xml version="1.w3. world!</title> </head> <body> <f:view> <h:form> <h:outputText value="Your Name: "/> <h:inputText value="#{helloBean.sun. <jsp:root xmlns:jsp="http://java.name}"/> <h:outputText value="Your Age: "/> <h:commandButton value="Say Hello" action="#{helloBean.faces.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“).com/JSP/Page" xmlns:f="http://java. the FacesServlet automatically translates these tags to a HTML form.page contentType="text/html"/> <html xmlns="http://www. all JSF tags can be used. As soon as we define the JavaServer tag namespaces (core and html).com/jsf/core" xmlns:h="http://java. Hidden input fields are used to transmit state information about the client or server. After translation.1"> <jsp:directive. world!</title></head> <body> <form id="main" name="main" method="post" action="/helloWorld1/faces/hello. IBM WebSphere or Oracle JDeveloper.org/1999/xhtml"> <head> <title>Hello.sayHello}"/> </h:form> </f:view> </body> </html> </jsp:root> For the web page designer. the inputText to a input tag and the submit button to a submit input tag.

Add managed bean declarations to the application configuration file (Faces Config). Develop the Model Object (business logic) Develop the backing beans with the properties as well as the used action methods.1. 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. Section 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. Client Server HTML Page HTTP Faces Servlet JSF View HTML Elements UI Components EL Backing Bean Model Object JSP Page Faces Config 8 . cf. 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).10) to bind UI component values and objects to backing bean properties or to reference backing bean methods from UI component tags.

they have properties. not on the client. The outcome of an action method can be used to specify the next page to be shown (navigation). Providing these UI elements as components makes development much easier. the backing beans are automatically updated.2 The JSF Concepts The following is a UML class diagram showing the different concepts of JSF. Unlike Swing.. In order to use a UIComponent. Backing beans contain event listeners and action methods. Converters translate and format the components value and generate an error message (if necessary). text fields. Event listeners consume events and can execute model objects. command buttons. which perform the core application logic.). . This means. such as the color or the default value. buttons. 9 . In JSF applications. CSS and JavaScript. and support event handling. 1. JSF provides all the standard components like labels. because the core functions are encapsulated within a reusable package. Validators verify the value of a component and generate an error message (if necessary). JSF applications communicate by events. and you don't have to develop any complicated combinations of HTML.1. which are displayed by the dedicated renderer. On user input. hyper links. In general. model objects don't know anything about the user interface. you just have to configure some properties. UIComponents are built as JavaBeans. This enforces a MVC-style architecture..3 UIComponents Like Swing components. list boxes. text fields. The view object contains a tree of UIComponents (output labels. methods. JSF UIComponents live on the server side. panels or data tables.

Whenever the value of the UIComponent changes. JSF handles validation in three ways: • at the UIComponent level • via validator methods in backing beans • in validator classes UIComponents usually handle simple validation. You can use a JSF EL expression to bind the value of a UIComponent with a specific backing bean property.1. the renderer extracts the request parameters (decoding).8 Events and Event Listeners In JSF applications there is no need of thinking in terms of HTTP requests and responses. JSF ships with converters for common types like dates. data model events (select a row for processing) and phase events (at the beginning and at the end of each phase in the processing life cycle. such as whether a value is required or not.7 Converters Converters translate an object to a string for display and from an input string to a Java object. Any component may fire one or more events. but anybody can develop additional converters which are applied internally during encoding and decoding. Events capture the way the user interacts with UI components.4 Renderers Not all JSF components are responsible for their own rendering. when JSF receives a response form the user. action events (clicking on a button or link).xml). 1. which means you register one or more event listeners with it. JSF supports the development of custom renderers as well. JSF allows separate classes to handle the rendering process. External validators are useful for generic cases. Navigation rules define what outcomes are understood and which page to load on what outcome. the associated backing bean property is automatically updated. they handle formatting and localization. There are four standard events: value-change events (value change of a component). Those classes are called renderers. Renderers create a visual representation for the client (encoding) and. You can attach one or more validators to any input component. 1. 1. see chapter 6).9 Navigation JSF provides an elegant navigation system. boolean or numbers. JSF provides a standard render kit for its UIComponents.5 Validators Validators are used to examine the correctness of the given input values. However. JSF uses JavaBeans to handle events with event listeners and handlers. Like Swing. JSF allows you to declaratively associate backing beans with UIComponents. 10 .6 Backing Beans In JSF applications the interaction between the model and the user interface is performed by backing beans. They contain properties you want to retrieve from the user and provide event listener methods which can act on these properties and perform some application processing. The navigation handler is responsible for deciding which page to load depending on the outcome of an action method. 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). These rules are defined in the JSF configuration file (faces-config. 1. 1. Furthermore.

• #{myBean. or to evaluate simple statements. EL expressions can be two way: they can retrieve a properties value or update it. JSF expressions are used to associate UIComponent properties with backing beans. it uses the same expression language as JSP 2.myProperty > 10} returns true. Method Expressions: • #{myBean.e.myMap['key']} returns the object stored under the key 'key' of the map myMap.name is not null.myProperty > 10} returns true.1. JSF 1.myMethod} assigns the method myMethod of the bean myBean. i. • • • The EL uses the number sign (#) to mark the beginning of an expression. Expressions with operators • #{myBean. without writing any Java code.2 depends on the unified EL API (javax. • • 11 . • #{not empty myBean.name}" /> renders this input text component only if helloBean. <h:inputText value="#{helloBean.10 The JSF expression language The main point of JSF expressions is to allow you to reference JavaBean methods.myProperty != 20 && myBean.sayHello}"/> assigns the action method „sayHello“ of the helloBean backing bean to the command button. if the (actual) value of myProperty is not equal to 20 and greater than 10. <h:commandButton value="Say Hello" action="#{helloBean. JSF 1. to read or update bean properties.myProperty} returns the value of myProperty of the object myBean. They are evaluated at runtime.myProperty} returns true. the empty string or an empty collection. if the (actual) value of myProperty in myBean is greater than 10. Value Expressions: • #{myBean. if myProperty is not null.2 uses the Unified Expression Language (EL). • #{myBean. • #{myBean. but you can use them for logical and mathematical statements as well.myList[2]} returns the second element of (the list or array) myList of myBean.1.el). Usage of EL expressions in tags: • <h:outputText value="#{helloBean.name}" rendered="#{not empty helloBean. EL expressions can also reference object methods.helloText}"/> associates the helloText property of the helloBean backing bean with the output text component.

12 .

jsp 1. value="#{helloBean. world!</title> 11. </head> 12. </html> 33. 7.age}"/> 26.helloText}" 16. xmlns:h="http://java. <h:inputText id="helloAge" 25. We start with the JSP page: 2.sun. <html xmlns="http://www. <h:commandButton id="sayHello" value="Say Hello" 28.1 Hello.0" encoding="UTF-8"?> 2. </h:form> 30. <link href="styles.1"> 5. <h:inputText id="helloInput" 20. <h:form id="main"> 15. <title>Hello.w3.sun. </body> 32. <h:outputText value="#{helloBean. </f:view> 31. </p> 22. xmlns:f="http://java.org/1999/xhtml"> 8. <h:outputText value="Your Name: "/> 19. </p> 27. <head> 9.com/jsf/core" 4.sun. <?xml version="1. where we learn to know all the key pieces which belong to a JSF application. <p> 23.com/JSP/Page" 3.css" rel="stylesheet" type="text/css"/> 10.page contentType="text/html"/> 6. value="#{helloBean. action="#{helloBean.name}"/> 21.</jsp:root> 13 .sayHello}"/> 29. <jsp:root xmlns:jsp="http://java.2 Easy Example: Hello World! We start with an easy but complete example. <jsp:directive. styleClass="header"/> 17. <h:outputText value="Your Age: "/> 24. <p> 18. <body> 13. <f:view> 14.com/jsf/html" version="2.

The jsp:directive is used to define the content type of the target HTML page. here "Say Hello". which is a container for other components and is used for posting information back to the server. Lines 8-11: The header of the HTML page. Lines 19: <h:inputText> creates a new HtmlInputText component that accepts text input.Lines 1 to 5: First. <f:converter> and so on). 14 . HtmlCommandButtons send action events to the application when they are clicked by a user. The value attribute defines the button label. we declare the namespaces for the core JSF tag libraries. Line 27: The <h:commandButton> specifies an HtmlCommandButton component. output labels and forms. Line 14: The <h:form> tag represents an HtmlForm component. JSF tags can use the usual CSS-styles of HTML. Line 15: The <h:outputText> tag creates an HtmlOutputText component. These provide custom tags like text boxes.name} references the property name of the backing bean. <f:validator>. which displays read-only text on the screen. but all input controls must be nested within a <h:form> tag. The action attribute references the action method that computes the new helloText. We can have more than one HtmlForm on the same page. JSF automatically synchronizes the value of the outputText with the helloText property. The value attribute #{helloBean.helloText} specifies an JSF Expression Language reference to the property helloText of the backing bean. The outcome of the action method can be used to handle navigation. whereas the core tags are independent of a particular render kit (like <f:view>. The „h“ tag library elements usually render HTML elements. Line 13: The <f:view> tag must enclose all other JSF related tags. Usually the prefixes „f“ and „h“ are used for these namespaces. The value attribute #{helloBean.

/** The hello text.age = age. 15 . */ public int getAge() { return age.2. Its return value can be used to define the next page (navigation). } /** Get the person name. } // property method for hello text // property methods for age // property methods for name } /** Define the text to say hello.java package helloWorld. */ private int age. } /** Get the hello text.name = name. It computes the new helloText.2 HelloBean. /** The age of the person. */ private String name. } /** Set the person name. return "hello". else helloText="Good Morning " + name + "!". */ public void setAge(int age) { this. whenever the „Say Hello“ button is pressed. public class HelloBean { /** The name of the person. } /** Set the age. */ public String getHelloText() { return helloText. } The sayHello() method is called. */ public String getName() { return name. */ private String helloText = "Hello World!". */ public void setName(String name) { this. /** Get the age. */ // action method for „Say Hello“ public String sayHello() { // button if(age < 11) helloText="Hello " + name + "!".

It is good practice to choose similar names for the bean class and its object. Furthermore.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.HelloBean </managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> </faces-config> In the faces-config.w3.sun.xml).xsd" version="1.FacesServlet</servlet-class> </servlet> <!-. JSF applications require that you specify the FacesServlet.Faces Servlet Mapping --> <servlet-mapping> <servlet-name>FacesServlet</servlet-name> <url-pattern>/faces/*</url-pattern> </servlet-mapping> <!-.xsd"> <display-name>Hello.0' encoding='UTF-8'?> <faces-config xmlns="http://java. All JSF requests are mapped to the FacesServlet.com/xml/ns/javaee/web-app_2_5.</description> <managed-bean-name>helloBean</managed-bean-name> <managed-bean-class>helloWorld.xml <?xml version="1.faces.0" encoding="UTF-8"?> <web-app version="2.jsp (e.jsp</welcome-file> </welcome-file-list> <!-.5" xmlns="http://java. #{helloBean. Those are automatically instantiated. Here the only managed bean is helloWorld.3 faces-config.xml file we declare all of the managed beans.jsp pages are xml documents --> <jsp-config> <jsp-property-group> <url-pattern>*.4 web.g.w3.name}).sun. World!</display-name> <description>Welcome to JavaServer Faces</description> <!-.com/xml/ns/javaee/web-facesconfig_1_2.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.com/xml/ns/javaee http://java. This name is also used in the EL expressions in hello.2"> <managed-bean> <description>The HelloBean.Welcome File --> <welcome-file-list> <welcome-file>faces/hello.sun.sun. The name of the bean object is helloBean. 2.2. 16 .webapp.HelloBean.com/xml/ns/javaee" xmlns:xsi="http://www.com/xml/ns/javaee http://java.sun.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.xml <?xml version='1.Faces Servlet : Front Controller --> <servlet> <servlet-name>FacesServlet</servlet-name> <servlet-class>javax. which is the main servlet (front controller) of the application.

com/xml/ns/javaee/web-app_2_5. jstl.com/xml/ns/javaee" xmlns:xsi="http://www.0"?> <web-app version="2.xml file (where all the JSF configuration is placed) and (if your web container doesn't already support JSF) the jar files of your JSF library.jar and standard.Welcome File --> <welcome-file-list> <welcome-file>path/firstPage. the required jar files for all JSF applications are jsf-api. all of the necessary files must be packed in a directory structure that can be deployed to the web container. there are two additions: the faces-config. This servlet is configured in the web.webapp.xml deployment descriptor file. <?xml version="1.faces. 3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.5" xmlns="http://java. jsf-impl.1 The Directory Structure Because JSF applications are standard Java web applications.sun.jsp</welcome-file> </welcome-file-list> 17 .2 The Deployment Descriptor JSF applications require a servlet. For the reference implementation (we use for this course).FacesServlet configuration and mapping --> <servlet> <servlet-name>Name of the Front Controller for your JSF Application.sun.jar. usually FacesServlet</servlet-name> <servlet-class>javax.jar.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> <!-.xml</param-value> </context-param> <!-.CONFIG_FILES</param-name> <param-value>/WEB-INF/faces-config.3 JSF Application Configuration 3.jar.com/xml/ns/javaee http://java.Configuration of faces-config file(s) (comma separated) --> <context-param> <param-name>javax. For JSF applications.w3.xsd"> <display-name>Display Name used by GUI Tools</display-name> <description>Description of the Web application </description> <!-.sun.faces. which acts as a front controller for the entire application (FacesServlet).

All elements of the configuration file must be enclosed within a <faces-config> element. that every request to a resource of the form http://myURL/pattern is handled by the JSF servlet. 18 . Usually.FacesServlet. The servlet-mapping makes sure. such as the supported locales and message resource bundle. All top level elements (application. to declare the backing beans and for the navigation configuration. The faces servlet will then handle the request with the corresponding JSP page. The second group of elements are used to define custom behaviour (e. you only need the first three configuration elements.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> The value of servlet-name is arbitrary. 3.. but the servlet-class must be javax.3 The JSF Configuration File The main configuration file for a JSF application is the faces-config.g. The other elements are used for advanced programming. custom validators or converters). factory) are optional and can be included once or more than once. managed-bean.faces.. The third group of elements is used to define advanced features like the registration of phase listeners.xml file. Chapter 8).. The first group of elements are used for general application configuration.webapp.all pages ending with . The faces-config elements The application element contains basic configuration information. . Strings defined in this bundle can replace standard validation and conversion error messages (cf.

or FacesContextFactory. The life cycle element allows you to register one or more phase listeners. custom validators and custom converters (cf. The managed-bean element is used to configure a managed bean. <description>. . 19 . generally used for tools. Chapter 6). validator and converter elements are used to declare custom components. <display-name>. which are executed before or after each phase of the Request Processing Life cycle (cf. The factory element provides a mechanism to define custom Factories like a custom Application. custom renderers. which will be created and initialized by the Managed Bean Creation Facility the first time it is requested by a JSF EL expression. The following figure shows the full hierarchy of the managed bean element. are optional elements..The component. Chapter 7). The managed-bean element has a subelement named managed-property which can be used to initialize any read/write properties (Setter Injection pattern). Every managed bean must be declared in a separate entry. render-kit. <icon>..

which means that the outcome may be produced by an arbitrary action method or even be a constant value. The next chapter shows a full example of a managed bean with initial values for (some of) its properties and different navigation rules. <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> . Each specific mapping between an outcome and a page is a navigation-case. because a managed bean can’t reference an object with a shorter life span than the managed bean itself. 20 . which means that this rule applies to all pages. For an example of a bean reference confer to the faces-config. The same result is achieved by omitting the <from-view-id> element. The fromPage value can also be an asterisk ( * ). Web applications usually have multiple pages. You must be careful about the scope of these objects.The managed property element can even be used to assign a reference to a previously defined managed bean.xml of the next chapter. and what pages to load based on those outcomes. (other navigation cases for this page) </navigation-rule> The from-action element can be left out. and we must have some way to move between them. . a navigation-rule defines what outcomes are understood. <display-name> and <icon> elements are optional and are generally used for tools. For any given page. . <description>.

5 Hello. world!</title> </head> <body> <f:view> <h:form> <h:outputText value="#{helloBean. 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. The hello. 21 .page contentType="text/html"/> <html xmlns="http://www.com/jsf/core" xmlns:h="http://java.age}"/> </h:panelGrid> </p> <h:commandButton value="Say Hello" action="#{helloBean. 3. the user loads the persons detail page.xml below).name}"/> <h:outputText value="Your Age:"/> <h:outputText id="helloAge" value="#{personDetails.sayHello}"/> <h:commandButton value="Details" action="details"/> <h:commandButton value="Goodbye" action="#{helloBean. the Goodbye button leads to the goodbye page.jsp page obtains two more buttons (Details / Goodbye). faces-config.sun.com/jsf/html" version="2.com/JSP/Page" xmlns:f="http://java.sun.4 Configuration and Navigation Example We extend our first easy example by introducing two new features: navigation rules and managed properties.sun.3.w3.org/1999/xhtml"> <head> <link href="styles.sayGoodbye}"/> </h:form> </f:view> </body> </html> </jsp:root> When we load the hello.1"> <jsp:directive.helloText}" styleClass="header"/> <p> <h:panelGrid columns="2" cellpadding="3"> <h:outputText value="Your Name:"/> <h:outputText value="#{personDetails.css" rel="stylesheet" type="text/css"/> <title>Hello.jsp page for the first time. the outputText fields for name and age get their values from the personDetails backing bean. By pressing the Details button.jsp <jsp:root xmlns:jsp="http://java.

age}" size="4"/> </h:panelGrid> </p> <p> <h:outputText value="Enter your favorite Numbers:"/> <h:panelGrid columns="3" cellpadding="3"> <h:inputText value="#{personDetails.6 PersonDetails.sun. The favorite numbers are saved in an array or vector of integers in the person details backing bean.0" encoding="UTF-8"?> <jsp:root xmlns:jsp="http://java.1"> <jsp:directive.favoriteNumbers[0]}" size="4"/> <h:inputText value="#{personDetails.page contentType="text/html"/> <html xmlns="http://www. <?xml version="1. The back button leads back to the hello page.com/JSP/Page" xmlns:f="http://java.org/1999/xhtml"> <head> <link href="styles.sun.name}"/> <h:outputText value="Your Age:"/> <h:inputText id="helloAge" value="#{personDetails. All of these properties read their initial value at creation time from the faces-config.com/jsf/core" xmlns:h="http://java.3.sun.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. 22 .favoriteNumbers[1]}" size="4"/> <h:inputText value="#{personDetails.com/jsf/html" version="2.w3. age and the favorite numbers of the given person.jsp The PersonDetails page can be used to change the properties for name.favoriteNumbers[2]}" size="4"/> </h:panelGrid> </p> <h:commandButton value="Back" action="back"/> </h:form> </f:view> </body> </html> </jsp:root> The panelGrid components above is used to align the two input text fields for name and age.xml file.

sun. As long as the same session is in use.sun.8 faces-config.2"> 23 . world! </title> </head> <body> <f:view> <h:form> <h:outputText value="#{helloBean.1"> <jsp:directive. This instance can be referenced with the expression #{personDetails} (or #{sessionScope.0" encoding="UTF-8"?> <jsp:root xmlns:jsp="http://java.w3. The properties are initialized with <managed-property> elements.com/xml/ns/javaee/web-facesconfig_1_2.7 Goodbye.org/1999/xhtml"> <head> <link href="styles.com/jsf/core" xmlns:h="http://java.helloBean backing bean.css" rel="stylesheet" type="text/css"/> <title>Hello.com/jsf/html" version="2.helloText}" styleClass="header"/> </h:form> </f:view> </body> </html> </jsp:root> 3.0' encoding='UTF-8'?> <faces-config xmlns="http://java.page contentType="text/html"/> <html xmlns="http://www. The same holds for the helloWorld.xsd" version="1.jsp The goodbye.com/JSP/Page" xmlns:f="http://java.w3.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. favoriteNumbers is a vector of (three) numbers. the same instance of personDetails will be used.com/xml/ns/javaee" xmlns:xsi="http://www. as it only prints out the goodbye helloText.sun.sun.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java. The vector is initialized by the <list-entries> element and its three <values> children. The <value> element contains the default value of the property specified in the <property-name> element. The corresponding setFavoriteNumbers method takes a Vector or a List of values as input argument.sun.3.sun. Setter Injection pattern). The Bean Creation facility uses the associated setter method to assign the initial values to the right properties (Property Injection: cf. <?xml version="1. <?xml version='1.personDetails }).jsp page doesn't need a backing bean for its own.com/xml/ns/javaee http://java.

the helloBean backing bean needs a reference to the personDetails backing bean.<managed-bean> <description>Detail Information of a person</description> <managed-bean-name>personDetails</managed-bean-name> <managed-bean-class>helloWorld.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. 24 .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.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.Vector</property-class> <list-entries> <value-class>java. The reference to the previously defined managed bean (PersonDatails) can be assigned to the helloBean via a normal JSF EL expression (Dependency Injection).lang.util.

3.sayGoodbye}</from-action> <from-outcome>goodbye</from-outcome> <to-view-id>/goodbye. • Pressing the „Details“ button leads us to the personDetails. Therefore the hello.jsp page. we find three navigation cases for hello. • Pressing the „Goodbye“ button executes the sayGoodbye action method which produces the outcome „goodbye“. <!-.jsp</from-view-id> <navigation-case> <from-action>#{helloBean.jsp</from-view-id> <navigation-case> <from-outcome>back</from-outcome> <to-view-id>/hello. the sayHello action is processed which produces the outcome „hello“.</description> <from-view-id>/details.jsp page: • By pressing the „Say Hello“ button. • From the personDetails page we can go back to the hello.jsp page.sayHello}</from-action> <from-outcome>hello</from-outcome> <to-view-id>/hello.navigation rules --> <navigation-rule> <description>Navigation from the hello page.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>details</from-outcome> <to-view-id>/details. which leads us to the goodbye.jsp and one for the personDetails.jsp</to-view-id> </navigation-case> <navigation-case> <from-action>#{helloBean.jsp page by pressing the „Back“ button.9 Navigation In the faces configuration file.jsp</to-view-id> </navigation-case> </navigation-rule> </faces-config> 25 .jsp</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <description>Navigation from the Person Details page.jsp page will be reloaded (with the new values entered by the user).</description> <from-view-id>/hello.

getName() + "!".getAge() < 11) helloText = "Hello " + personDetails. } /** Define the text to say goodbye.java file has a new action method for the Goodbye button: sayGoodbye(): package helloWorld. */ public void setHelloText(String text) { helloText = text.getAge() < 11) helloText = "See you. /** Set the person details reference.java The helloBean. else helloText = "Good Morning " + personDetails.getName() + "!".3. } /** Define the text to say hello. */ public void setPersonDetails(PersonDetails personDetails) { this. */ public String sayGoodbye() { if (personDetails.getName() + "!". } /** Get the hello text. } /** Set the hello text. */ public String sayHello() { if (personDetails. } } 26 . return "hello".personDetails = personDetails. */ public String getHelloText() { return helloText. public class HelloBean { /** The reference to the person deatils backing bean */ private PersonDetails personDetails.10 HelloBean.getName() + "!". " + personDetails. */ private String helloText. /** The hello text. else helloText = "Goodbye " + personDetails. return "goodbye".

1)"/> </h:panelGroup> <h:outputText value="(2.2. We start with the basic attributes. When we specify two columns. border.4 The Standard JSF Components In this chapter. <h:panelGrid columns="2" headerClass="page-header" cellpadding="1" border="1" width="40%"> <h:outputText value="(1. typically a value binding • required: A boolean value. You can also configure header and footer with facets that map to the <thead> and <tfoot> table subelements. Child components are organized according to the specified number of columns. respectively.1)"/> <h:panelGroup> <h:outputText value="(1. You can expect third-party developers to provide additional components as well.1.1)"/> <h:outputText value="(1. The width.1 The Layout of the Components HtmlPanelGrid is useful for creating arbitrary. Here we will focus on the most important components only. Unlike the HTML table.1)"/> <h:outputText value="(2. which are applicable to most of the components. if true a value is required for this input field • styleClass The CSS class name which should be used for this component 4.2)"/> </h:panelGroup> <h:panelGroup> <h:outputText value="(2.2)"/> </h:panelGrid> The HtmlPanelGroup component groups a set of components together.2.1)"/> <h:outputText value="(2.1)"/> <h:outputText value="(1. so that they can be treated as a single entity. <h:panelGrid columns="2" headerClass="page-header" cellpadding="1" border="1" width="40%"> <f:facet name="header"> <h:outputText value="This is the table header"/> </f:facet> <h:outputText value="(1.2. • id: An identifier for a component • rendered: A boolean value.2)"/> </h:panelGrid> 27 . static component layouts (it maps to the <table> element). and so on. the next two form the second row. the first two components form the first row (one per column).2)"/> <h:outputText value="(2. They provide the basic set of functionality necessary for building HTML-based web applications. if set to false suppresses rendering of this component • value: The components value. and cellpadding properties are passed through to the HTML table. we cover the standard components that all JSF implementations must support. you don’t have to explicitly denote columns and rows.

HtmlInputText is the most common input control. but it is restricted to a single line.helloText}" styleClass="header"/> <h:outputText value="#{helloBean. .2 The Output Components The purpose of the output components is to display data. ChoiceButton. HtmlOutputText converts the given value to a string and displays it with optional CSS style support. This allows target devices to define shortcuts for input elements.). You can specify literally the data that they display or have them display properties from backing beans. Example: <h:outputText value="#{helloBean. <h:inputTextarea value="#{helloBean. you can use the HtmlInputTextarea component.age}" size="4" disabled="true"/> The size and disabled properties are passed through to the HTML input tag. Example <h:panelGroup> <h:outputLabel for="helloInput" accesskey="N"> <h:outputText value="Your Name:"/> </h:outputLabel> <h:inputText id="helloInput" value="#{helloBean. If you need a multi line input field. the component is associated via a value-binding expression with the name property of helloBean.. HtmlOutputLabel is translated to the HTML <label> element..name}" size="30" required="true"/> <h:inputText id="helloAge" value="#{helloBean.4. It maps to a simple text field—the <input> element with type “text”.name}" required="true" accesskey="N"/> </h:panelGroup> 4. The most basic output component is HtmlOutputText (<h:outputText>).goodbyeText}" styleClass="header"/> The HtmlOutputLabel component is used for associating labels with form elements (InputText. In this example.helloText}" rows="5" /> 28 .3 The Basic Input Components The HtmlInputText component is used for basic user input. <h:inputText id="helloInput" value="#{helloBean.

<f:selectItem itemValue="0" itemLabel="cats"/> <f:selectItem value="#{myBean. only one of these components is described here: HtmlSelectOneMenu. <h:inputSecret value="#{user.The HtmlInputSecret component is used to display a password input field. If you want to associate multiple check boxes with a single property. In JSF. HtmlSelectOneRadio. and has a value. The number of items displayed is always one.4 Choice Input Components User interfaces often allow a user to select one or more items from a set of possible choices. <h:outputLabel for="accepted" accesskey="A"> <h:outputText value="Accepted"/> </h:outputLabel> <h:selectBooleanCheckbox value="#{helloBean. a selection item represents a single choice. like HtmlSelectManyCheckbox and HtmlSelectOneListbox. a description.animalList}"/> These selectItem(s) tag can be used to configure another component’s selection list (e. Components in the SelectMany and SelectOne families. itemLabel. we can use a HtmlSelectBooleanCheckbox component. 29 . and a label. <f:selectItems value="#{myBean. 4. for components like HtmlSelectManyCheckbox. Any text the user types is displayed using the asterisk or some other character (depending on the browser). Therefore.password}" size="10" maxlength="10"/> For the input of boolean values. so the result is a combo box (also called a drop-down list box). you preferably use a HtmlSelectManyCheckbox (see next chapter). and itemValue properties or a value-binding expression. You can either use the value itemDescription. HtmlSelectOneListbox or HtmlSelectOneMenu). All of these choice components work in a similar way.animal[3]}"/> Alternatively.accepted}" id="accepted"/> The selectBooleanCheckbox component works fine for a single check box on a form. A UISelectItem component are used to display items in a list and to select one or more items from this list. display lists of items. HtmlSelectOneMenu displays its child items in a list box using the HTML <select> element. you can use a selectItems tag with a value binding to a list or array of elements.g.

as list of strings) or in the faces configuration file. you have to provide an array or a list property named animals. } public void setAnimal(String a) { this.<h:outputText value="Your Favorite Animal "/> <h:selectOneMenu id="animal" value="#{helloBean. } 30 .animal = a.g. } public void setAnimals(List<String> items) { animals = new ArrayList<SelectItem>(). private List<SelectItem> animals. for (String item : items) animals. which can either be initialized in the backing bean (e.</description> <managed-bean-name>helloBean</managed-bean-name> <managed-bean-class>helloWorld.add(new SelectItem(item)). } public List<SelectItem> getAnimals() { return animals. Initialization in the faces configuration file (faces-config. you have to provide the corresponding get and set methods for the favorite animal and the selection list of animals: private String animal.animal}" accesskey="A"> <f:selectItems value="#{helloBean.xml): <managed-bean> <description>The one and only HelloBean. public String getAnimal() { return animal.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.animals}"/> </h:selectOneMenu> In the corresponding JavaBean.

HtmlDataTable uses the column components as a template for each column. } The Person class provides the corresponding entries: public class Person { String firstName.firstName = firstName. If the row property is specified. If the facet tag has a name=“header“ attribute. public Person[] getFriends(){ return friends. private Person[] friends = { new Person("Hans". a lastName and an age attribute. String lastName. String lastName. 33). "Meier".lastName}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="First Name"/> </f:facet> <h:inputText value="#{person. this. this. it displays that many rows (starting with the first).4.age}"/> </h:column> </h:dataTable> In the backing bean. Person(String firstName. <h:dataTable value="#{helloBean. "Muster". it is translated to a <thead> (table header) HTML tag. 22)}.friends}" var="person" first="0" rows="2"> <h:column> <f:facet name="header"> <h:outputText value="Last Name"/> </f:facet> <h:inputText value="#{person. } 31 .5 Data Tables The HtmlDataTable component displays an HTML <table>. you have to provide a corresponding list of friends (here Person) with a firstName. new Person("Peter". int age. For each row.age = age. int age){ this. new Person("Heidi".lastName = lastName.firstName}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Age"/> </f:facet> <h:inputText value="#{person. 44). The columns are specified with column components. The var property defines the name of the iterator variable (here person). "Schmid".

DataModel instead of the previous array of Person.lastName}"/> </h:commandLink> </h:column> <h:column> <f:facet name="header"> <h:outputText value="First Name"/> </f:facet> .personModel}" var="person" border="1" cellspacing="0" rows="2"> <h:column> <f:facet name="header"> <h:outputText value="Last Name"/> </f:facet> <h:commandLink action="#{personHandler. } public String getLastName(){ return lastName.faces. The LastName column uses an <h:commandLink> component instead of an outputText and the value of the <h:dataTable> is now an instance of javax. JSF offers a much easier way to represent tabular data through the abstract DataModel class.public String getFirstName(){ return firstName. . but there are some important differences. In the JSF table we have to change the following entries: <h:dataTable value="#{personHandler. To implement this feature.model. DataModel has two subclasses: ListDataModel and ArrayDataModel. } public void setFirstName(String firstName){ this. </h:column> </h:dataTable> The table looks similar to the previous one. 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. These are convenience implementations of the abstract DataModel class with the following properties: 32 . } 4. However. . . } .6 Processing Row-Specific Events A very common application feature is to have a table with summery information where each row is linked to the details about the item in that row. . we must figure out which table row the user selected to make the corresponding details available for display.firstName = firstName.select}" immediate="true"> <h:outputText value="#{person.

it populates the ArrayDataModel with the Person array returned by getPersons(). Then.• • • • • boolean: rowAvailable is true.*. if no row is selected) Object: wrappedData is the object representing the table.faces.getRowData(). 33 . private Person selectedPerson. } public String select() { selectedPerson = (Person) personModel. package helloWorld. private HelloBean helloBean.faces. false otherwise.model. Other sublasses of DataModel are ListDataModel (for Lists) or ResultSetDataModel (for a JDBC ResultSet).model.getFriends(). } } The getPersonModel() method creates an instance of the javax. The renderer together with the UIData component ensure that the DataModels rowIndex is positioned to the selected row when the action method is invoked. public class PersonHandler { private DataModel personModel = new ArrayDataModel().ArrayDataModel class which is a subclass of DataModel. import javax. when the rowIndex property holds the index of an existing row. } public Person getSelectedPerson() { return selectedPerson. we can use getRowData() in the select() method to read the data of the selected person. return personModel. } public void setHelloBean(HelloBean helloBean) { this.setWrappedData(getPersons()). 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. } public Person[] getPersons() { return helloBean. The <h:commandLink> in each table row is bound to the PersonHandlers select() method. All we need is a new PersonHandler class as a wrapper for the array of Person objects. Therefore. return "success". The <h:dataTable> uses the personModel DataModel to read the table entries from.helloBean = helloBean. There are no changes necessary in the HelloBean or Person class. public DataModel getPersonModel() { personModel.

4.sayGoodbye}"/> The corresponding action Methods are defined in the backing bean: public String sayHello() { if (age < 11) helloText = "Hello " + name + "!".7 The Command Components The command components represent an action initiated by the user. return "hello". <h:commandButton value="Say Hello" action="#{helloBean. } 34 . Because they perform the same operation. their usage is quite similar.sayHello}"/> <h:commandButton value="Goodbye" action="#{helloBean. The two standard command components are HtmlCommandButton (for displaying a button) and HtmlCommandLink (for displaying a hyper link). else helloText = "Good Morning " + name + "!".

5 Messaging 5. but that’s not a requirement. • Fatal . <h:message for="helloInput" showDetail="true" showSummary="true" errorStyle="color: red"/> The attributes showDetail and showSummary are optional. Whenever possible. • Info . ) can generate messages. HtmlMessage is designed to display a message for a specific UI component. You can insert an infoClass or an infoStyle attribute to define a CSS class / CSS style for messages with Info severity. • Warn . • Error . the error is placed next to the component (so the user knows where the problem arises).Represents an informational text to be send back to the user. Messages contain a summary and a detail text. Every message has a severity level which is equal to one of the following values. If you need to display multiple messages for a page. You can insert an errorClass or an errorStyle attribute to define a CSS class / CSS style for messages with error severity. these messages have to be displayed to the user. You can insert an fatalClass or a fatalStyle attribute to define a CSS class / CSS style for messages with fatal severity. If more than one message is registered for a component (which can happen if more than one validator is registered. The default value for showDetail is true. that for showSummary is false. Example: all messages for this page: <h:messages showDetail="true" showSummary="true" layout="table" errorStyle="color: red"/> 35 .You can insert a warnClass or a warnStyle attribute to define a CSS class / CSS style for messages with Warn severity. converters.1 Messages Multiple parts of a JSF application (validators. Usually.Indicates that an error may have occurred. application exceptions .Indicates a serious (application) error... and is useful whenever you need to inform the user of any errors.Indicates an error like validation or conversion error. It is typically used with input controls. HtmlMessage displays only the first one. Example: Message for input control helloInput. you should use HtmlMessages instead. or if a validator has problems with conversion).

it will look for them in the JSP page and in the custom messages bundle (messages.IntegerConverter.INTEGER_detail=The input value should be an integer like 17.sun.5.2 Overriding standard Messages All of the standard validators and converters have default messages. Therefore we often would like to override these texts with custom messages. .UIInput. creating a message for an empty input field with a required=“true“ attribute: javax.component.converter. – converterMessage for conversion errors and – validatorMessage for validation errors. we would find the following key/value pair.UIInput. We can override the default messages by a custom message bundle.faces. In the reference implementation.converter. the details message texts are often missing. </faces-config> Once. 36 . which is configured in the faces-config. messages. you have defined a message bundle.faces.CONVERSION={0}: Conversion error occurred.component.faces.component. Possible values are – requiredMessage for required input. <h:inputText id="helloInput" value="#{helloBean. you can selectively override the standard messages. it will take the predefined standard message.properties file at /WEB-INF/classes --> <message-bundle>messages</message-bundle> </application> .faces. Only if there is no user defined message.faces. these default messages are not very user friendly. for example. javax. javax. validator or converter looks for an error message.UIInput. The messages.html for the list of message keys). javax.REQUIRED=Input value for {0} is required.REQUIRED_detail=Input value for {0} must not be void. as long as you use the correct keys (see java.xml file: <faces-config> <application> <!-.IntegerConverter. javax.UIInput.g. .properties). These are configured using a normal Java message bundle. Each JSF application can be associated with a single message bundle (e. In general.REQUIRED={0}: Validation Error: Value is required.component.messages.name}" required="true" requiredMessage="Please enter your name into this input field"> Furthermore.INTEGER=The given input value '{0}' is not an integer. Whenever a JSF component.properties file then might look as follows: javax.com/javaee/javaserverfaces/ 1.2_MR1/docs/api/index. One possibility is to define an error message in the tag of the corresponding input component.faces. The used parameters are defined in the JSF documentation for the corresponding messages.properties).

getCurrentInstance(). helloText = "Hello!". message). */ public String sayHello() { if (!isValidName(name)) { // create faces message FacesMessage message = new FacesMessage(FacesMessage. you can create a message in your backing bean (or validator or converter class or method). The FacesMessage constructor takes the arguments severity.SEVERITY_ERROR.3 Constructing Application Messages Whenever one of your backing beans throws an exception or when an error occurs in your application logic (e. if the message does not belong to any component) and the FacesMessage. /** test whether given string is a valid name. } letter 'A'"). If we want to retrieve the application messages only (the messages.g. The addMessage function takes two parameters: the message id (either the component id or null. "Name is not valid!". Application messages do not belong to any component on the jsp page. For this. you want to inform the users about this. else helloText = "Good Morning " + name + "!".addMessage(null.5.charAt(0) == 'A'). */ private boolean isValidName(String s) { return (name. 37 . Creating a Faces Message in the Backing Bean In the following action method we create a FacesMessage to inform the users about errors in the name input field.length() > 0 && name. } You have to add this messages to the FacesContext. the summary string and the detail string.addMessage(null. /** Define the text to say hello. which belong to no component) we use the globalOnly attribute: <h:messages globalOnly=“true“>. context. "Your name must not be empty and not start with // add message to faces context FacesContext context = FacesContext. } return "hello". from where the JSP page will read it afterwards: context. system or connection errors). } else { // name is valid if (age < 10) helloText = "Hello " + name + "!".message)).

// ( 1 ) if (name == null) name = FacesMessage. you preferably use the custom message bundle to define your application messages and read these message texts from there. // ( 3 ) summary = MessageFormat. Therefore.getMessageBundle(). // ( 3 ) detail = MessageFormat.FACES_MESSAGES. 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.format(detail. detail = bundle.. FacesContext context = FacesContext. params) { String summary = "?? key " + key + " not found ??". you want to read those messages from a message bundle. instead. Object.getApplication(). String detail = null.getBundle(name). String name = context. ResourceBundle bundle = ResourceBundle.getString(key).format(summary. The following MessageFactory provides us with the desired FacesMessage: public class MessageFactory { public static FacesMessage getMessage(FacesMessage.Severity severity. // ( 2 ) try { summary = bundle. detail). Usually.getString(key + "_detail"). In your backing bean. // ( 4 ) } } 38 . String key.. params).getCurrentInstance(). } catch (MissingResourceException e) {} return new FacesMessage(severity. params). summary.Retrieving Message Texts from the Message Bundle In the previous example. In the following example we take this improved approach. we used hard coded message texts from our backing beans.

javax.faces.java /** Define the text to say hello.faces.REQUIRED_detail={0}: Input value must not be void.REQUIRED= This value is required. */ private boolean isValidName(String s) { return (name. if (!isValidName(name)) { // create hello message and add it to faces context context.addMessage(null.component. helloBean.charAt(0) == 'A'). HelloWorld4).properties file for the application message contains messages of the form: javax. } The messages.converter.INTEGER_detail={2}: The input value should be an integer like 17.IntegerConverter.length() > 0 && name.name}" required="true" requiredMessage="Please enter your name"/> <h:message for="name" errorClass="errorStyle" showDetail="false" showSummary="true"/> 39 . helloWorld. javax.converter.Example: Print out an information message for invalid name values (cf. "helloWorld.IntegerConverter. MessageFactory.jsp <h:form id="main"> <h:outputText value="#{helloBean. javax. } return "hello".getMessage( FacesMessage.getCurrentInstance(). helloText = "Hello!".UIInput.nameMessage". name)).nameMessage= Name ''{0}'' is not valid! hello. */ public String sayHello() { FacesContext context = FacesContext.helloText}" styleClass="header"/> <h:panelGrid columns="3"> <h:outputText value="Your Name"/> <h:inputText id="name" label="Name" value="#{helloBean.UIInput. } else { if (age < 10) helloText = "Hello " + name + "!". } /** test whether given string is a valid name.INTEGER=The given input value ''{0}'' is not an integer. else helloText = "Good Morning " + name + "!".component.SEVERITY_ERROR.faces.faces.

sayHello}"/> <h:commandButton value="Goodbye" action="#{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.<h:outputText value="Your Age"/> <h:inputText id="age" label="Age" value="#{helloBean.country}" required="true"/> <h:message for="country" errorClass="errorStyle" showDetail="false" showSummary="true"/> </h:panelGrid> <h:commandButton value="Hello" action="#{helloBean.sayGoodbye}"/> <p> <h:messages layout="table" showDetail="true" showSummary="false" infoClass="infoStyle" errorClass="errorStyle" globalOnly="false"/> </p> </h:form> We then obtain either one or more error messages (in case of any input errors): or the application message created by the MessageFactory: 40 .

defined as phases of a request processing life cycle. the components in the view are asked to perform tasks in a certain order. event listeners.1 • • • • Restore View Extract the view ID and find current view Look up the components for the current view. validators and converters If there is no (new) user input. skip to render response phase (6) 41 . create them if necessary Restore or create the component values. The following graphic shows the main tasks for each phase. 6.6 Request Processing When a JSF view is requested.

application). This can be used for example for Cancel buttons. 6. If the immediate attribute of a component is set to true.2 • • • • Apply Request Values Decoding: extract all user input from the input fields (and save them in the submittedValue attribute of the component). 6.5 • • • • Invoke Application Handle all fired events. Invoke the converters (object to string). 6.6. 6. the corresponding actions will be fired in this phase instead of the invoke application phase. If the local value has changed. the control will skip to the render response phase (6). session. validation takes place in this phase instead of the process validation phase. a valueChangeEvent is fired and consumed by the registered listeners. which update the backing bean with the (new) validated and converted local values of the components. Display the next view with the new values from the backing beans. the value is validated and set as the local value of this component. Call the event handler methods of all registered event listeners.3 • • • • Process Validation Convert submitted values: Convert the value of the submittedValue attribute of the component from string type to object. 42 . If there is a command button or a hyper link with an immediate property set to true. because it prevents the validation of any input fields. Choose the next page based on the action method's outcome. Validate submitted values: After conversion. If the conversion or the validation process throws an exception. The set methods of these properties are called.4 • • Update Model Values Evaluate the JSF EL expressions in the components' value attribute to find the associated backing beans and properties (depending on the beans' scope: request. Create action events and add them to the faces context for later processing. Execute default action listener method.6 • • • Render Response Save the state of the new view for later use in the restore view phase (1).

These error messages can then be displayed back to users with a <h:message> or <h:messages> tag. and third-party vendors will provide them as well. like May 23. JSF provides a set of standard converters to satisfy the basic type conversion needs. As with validators. 7. The associated object in the backing bean is updated only if the value is accepted. on the other hand. <h:inputText id="helloAge" value="#{helloBean. 1980.7 Validators and Converters JSF supports validation and conversion through validator or conversion methods of backing beans and validator and converter objects. A Java Date object. Otherwise. Two Date objects can be compared and we can compute the elapsed time between the two dates. they see it in terms of recognizable text. Validation checks the value of a control to see if its current value is acceptable. is much more than just a string. converters create converter exceptions and send them back to the user as faces messages. When users see an object on the screen. and the associated object is not modified. You can also write your own converters.name}"> <f:validateLength minimum="2" maximum="10"/> </h:inputText> <h:message for="helloInput" styleClass="errorMessage"/> <f:validateLongRange> and <f:validateDoubleRange> can be used to ensure that the (long/double) value inserted in the input field is greater than or equal to the specified maximum (long/double) value (smaller than or equal to the minimum value). and to create an object representation of a string.to create a string representation of an object.dateOfBirth}"> <f:validateLongRange minimum="0" maximum="120"/> </h:inputText> <h:message for="helloAge" styleClass="errorMessage"/> 43 .1 Standard Validators JSF includes a few standard validators for the most common validation problems: <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. This is the purpose of a converter . an error message is generated for that specific component. <h:outputText value="Your Name:"/> <h:inputText id="helloInput" value="#{helloBean.

trim(). /** The identifier of the error message. UIComponent component. throw new ValidatorException(message).SEVERITY_ERROR. */ public static final String VALIDATOR_ID = "NameValidator".INVALID_NAME"). } } } To ensure that this validator class is instantiated. public class NameValidator implements Validator { /** The identifier of the validator.name}" validator="#{helloBean.toString(). The validator interface demands for one method: validate(). public void validate(FacesContext context. validator classes are generic and designed for use in different applications. UIComponent component. For any input component you can register one or more validators.2 Validator Methods An input field can also be associated with a validation method on a backing bean.trim(). Validation methods are generally used for application specific validation and can not be reused for different applications.7. throw new ValidatorException(message).xml file: 44 .getMessage( FacesMessage.nameCheck}"> <f:validateLength minimum="2" maximum="10"/> </h:inputText> The corresponding nameCheck method in the backing bean: public void nameCheck( FacesContext context.toString(). Object value) { if (!value. "NameValidator. On the other hand. we have to declare it as validator in the facesconfig. <h:inputText id="helloInput" value="#{helloBean. Object value) { if (!value.3 Validator Classes Validator classes raise some additional work. INVALID_NAME_MESSAGE_ID). */ public static final String INVALID_NAME_MESSAGE_ID = "NameValidator.matches("[A-Z][a-z]*")) { FacesMessage message = MessageFactory. } } 7.matches("[A-Z][a-z]*")) { FacesMessage message = MessageFactory.SEVERITY_ERROR.getMessage( FacesMessage.INVALID_NAME".

Character. . </managed-bean> <navigation-rule> . 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. Byte. #.00"/> </h:inputText> We would obtain a similar result by the code: <h:inputText value ="#{helloBean. The JSF framework has standard converters for all the basic Java types: BigDecimal. . BigInteger. Integer.price}"> <f:convertNumber pattern="SFr. . Short. So for all these types.dateOfBirth}"> <f:convertDateTime type="date"/> </h:inputText> f:convertDateTime can be used to convert a Date object to a string (and vice versa). <h:inputText value="#{helloBean. .<faces-config> <managed-bean> .name}"> <f:validator validatorId="NameValidator"/> </h:inputText> 7.4 Automatic Conversion If you don’t specify a converter. </navigation-rule> <validator> <validator-id>NameValidator</validator-id> <validator-class>helloWorld. and Long. All primitive types are converted to their object counterparts. Double.price}"> <f:convertNumber maxFractionDigits="2"/> </h:inputText> 45 . Boolean.5 Standard Converters There are two converter tags: <f:convertDateTime> and <f:convertNumber> <h:inputText value="#{helloBean. The type attribute is optional and can be either date or time or both. conversion is performed automatically. 7. JSF will pick one for you.NameValidator</validator-class> </validator> </faces-config> This class can then be used as validator in any JSP page: <h:inputText id="helloInput" value="#{helloBean. Float.##0.

/** The identifier of the error message. public Object getAsObject(FacesContext context. which is automatically converted into the corresponding country name.toString(). UIComponent component.CountryConverter </converter-class> </converter> 46 . } public String getAsString(FacesContext context. return value.xml file: <converter> <converter-id>CountryConverter</converter-id> <converter-class>helloWorld. throw new ConverterException(message). and also provide sophisticated formatting functionality for dates and numbers.country}"> <f:converter converterId="CountryConverter"/> </h:inputText> The converter has to be configured in the faces-config.INVALID_COUNTRY_KEY".. public class CountryConverter implements Converter { /** The identifier of the converter. */ public static final String COUNTRY_CONVERTER_MESSAGE_ID = "CountryConverter. String value) throws ConverterException { if(value.get(value). the user can insert a two letter country code. or accept input for that special data type. } if(countries.getMessage( .6 Using Custom Converters In many cases. the standard converters will be sufficient.containsKey(value)) return countries.7. ). In our example. Object value) throws ConverterException { return value.. } } You can use this converter in the JSP page: <h:inputText id="country" value="#{helloBean. UIComponent component.trim(). */ public static final String CONVERTER_ID = "CountryConverter". String> countries. they handle all of the standard Java data types. HashMap<String.length() < 2) { FacesMessage message = MessageFactory. 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.

The var attribute specifies the name which is used in your JSF component tags. French and German). 8. With JSF 1. if we had nested them deeper. Both attributes (basename and var) are required. .jia. If the resource bundle can not find a key. . All you have to do is to define the proper resource bundle in the faces-config file.8 Internationalization Enabling an application to support multiple locales is called internationalization. you can grab a particular string from that bundle with an ordinary value-binding expression such as #{label.texts”. Once the bundle has been loaded. the basename would be “org. <f:view . The following tag loads the bundle and stores it in the request scope. > <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. . > <f:loadBundle basename="texts" var="label"/> . . The process of modifying an application to support a (new) locale is called localization. provide localized messages for validator and converter errors for certain languages (English.theKey}. prefixed by its location in your classpath. Some implementations. . 47 . <faces-config .1 you had to define the texts with the <f:loadBundle> tag. no prefix is needed. like the reference implementation. However. it will return the string “??? key ???” instead... <f:view> The basename attribute specifies the name of the resource bundle.1 Load the Resource Bundle Using a resource bundle in a JSF application is as simple as using a value-binding expression. like in the WEB-INF/classes/org/jia directory.

So the key „helloWorld“ points to the string that represents the welcome message. </faces-config> 8.. whether it is in English.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. or German.properties helloWorld=Hallo. French. Resource bundles are normal property files with key/value pairs. 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. which is the same for all locales.. texts_de. 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> . world! yourName=Your Name dateOfBirth=Date of Birth country=Country hello=Hello goodMorning=Good Morning goodbye=Goodbye seeYou=See you 48 .8.3 Creating Resource Bundles Resource bundles are not a JSF feature—they are a fundamental part of the way Java handles internationalization and localization. Each string has a key.

goodbye}" action="#{helloBean. 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.getCurrentInstance().getLocale(). } catch (MissingResourceException e) {} return text. } You can use this method to extract the correct string from the bundle: helloText = getText("goodbye") + " " + name + "!".. Locale locale = context.yourName}"/> <h:outputText value="#{label.getViewRoot(). you can configure an application-wide message bundle. a getText method like the following can be useful: private String getText(String key) { String text = "???" + key + "???". The name of your message bundle (here messages) and the supported locales have to be defined in the faces-config.. </faces-config> 49 . 8.xml file: <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> .dateOfBirth}"/> <h:commandButton value="#{label. text = bundle.8. try { FacesContext context = FacesContext.4 Using Resource Bundles Once you have created one or more resource bundles.5 Constructing Localized Messages In order to localize your error or information messages.getBundle("texts". locale). ResourceBundle bundle = ResourceBundle.getString(key).sayHello}"/> If you need localized texts in your backing beans.

INVALID_NAME=Invalid value for name.LengthValidator.MAXIMUM_detail=Der Eingabewert darf höchstens {0} Zeichen lang sein.validator. NameValidator.MINIMUM_detail=The input value must be at least ''{0}'' characters long.LengthValidator. CountryConverter.MINIMUM=Die Eingabe ist zu kurz.validator.MINIMUM_detail=Der Eingabewert muss mindestens {0} Zeichen lang sein.For each of the supported locales.INVALID_NAME_detail=Namenswert entspricht nicht dem Pattern [A-Z] [a-z]* CountryConverter. javax.validator.faces.faces.INVALID_NAME_detail=Name value does not match pattern [A-Z][a-z]* CountryConverter.validator.properties file: messages_de. javax. NameValidator.INVALID_NAME=Ungültiger Namenswert. CountryConverter.faces.validator.validator.validator.INVALID_COUNTRY_KEY=Invalid country key.faces. NameValidator.faces.properties (German message bundle) javax.MAXIMUM=Die Eingabe ist zu lang. NameValidator.MAXIMUM_detail=The input value can''t be more than ''{0}'' characters long. javax.MAXIMUM=Input value too long.validator.INVALID_COUNTRY_KEY=Ungültiger Ländercode.LengthValidator.INVALID_COUNTRY_KEY_detail=Land muss ein Ländercode aus 2 Buchstaben sein messages_en.properties (English message bundle) javax. javax.INVALID_COUNTRY_KEY_detail=Country must be a 2 letter country code JSF will use your bundles to override default validation and conversion error messages.faces.LengthValidator. The corresponding JSP page uses a normal message tag: <h:message for="country" styleClass="errorMessage"/> <h:messages showDetail="true" layout="table" styleClass="errorMessage"/> 50 .faces. you have to provide a corresponding messages_xx.faces. javax.MINIMUM=Input value too short.LengthValidator.LengthValidator.LengthValidator.LengthValidator. javax.

The FacesMessage constructor takes the arguments severity (SEVERITY_INFO. UIComponent component.getMessage( FacesMessage. summary = MessageFormat.java public class MessageFactory { public static FacesMessage getMessage(FacesMessage. */ public static final String VALIDATOR_ID = "NameValidator". locale). custom converter or custom validator. Object. String name = context.getApplication(). validator or converter.getViewRoot(). or SEVERITY_FATAL) summary string and detail string.trim(). detail = bundle.getBundle(name. FacesContext context = FacesContext. String detail = null. public void validate( FacesContext context. Object value ) { if (!value.toString().getMessageBundle().getString(key + "_detail"). The MessageFactory from chapter has to be changed somewhat to provide us with the desired localized FacesMessage: MessageFactory. params) { String summary = "?? key " + key + " not found ??". String key. SEVERITY_WARN. } } } 51 . detail = MessageFormat. INVALID_NAME_MESSAGE_ID). } } We can use this MessageFactory in any backing bean.Severity severity.SEVERITY_ERROR.6 Using Localized Message Bundles for Application Messages You can also use the message bundle to create your own (error) messages. if (name == null) name = FacesMessage. the name of the message bundle and from this the summary and detail string of the dedicated message.getCurrentInstance().INVALID_NAME".getLocale(). /** The identifier of the error message. params).getString(key). summary. } catch (MissingResourceException e) { } return new FacesMessage(severity. In your backing bean. to create localized error messages: public class NameValidator implements Validator { /** The identifier of the validator. SEVERITY_ERROR. ResourceBundle bundle = ResourceBundle. params). you can create a message (of type FacesMessage) by first extracting the client's locale. throw new ValidatorException(message). try { summary = bundle.format(summary.matches("[A-Z][a-z]*")) { FacesMessage message = MessageFactory.format(detail. detail).8. */ public static final String INVALID_NAME_MESSAGE_ID = "NameValidator.. Locale locale = context..FACES_MESSAGES.

52 .

and different IDE vendors provide many additional components. By implementing the StateHolder interface. 53 . These attributes are used as custom properties (e. 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.com). validators. we make sure that the state of the validator (its properties) is saved between different requests.1 The different parts of a Custom Tag To create a custom validator tag. a regular expression used by a custom validator to match certain input strings <g:validateRegex pattern="[a-z]{5}"/>). for example. Custom tags for validators and converters are implemented in the same way.jsfcentral. to find out about different JSF products and libraries. and converters. Many standard components are available already. you should make sure that there is no alternative way you can reach your goal: you can visit the JSF Central page (www. 9. The following sections show all the details needed to implement a custom validator tag.9 Custom Tags As we’ve already seen. However. we first have to write a CustomValidator class which implements the Validator and the StateHolder interfaces. With custom tags for validators or converters we are able to provide custom tag attributes.g. renderers. The validator Interface requires a public validate() method. JavaServer Faces has several services that enable you to build web applications quickly. Before you write a new custom tag or custom component. In this chapter we learn how to create our own custom tags.

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 { public Validator createValidator() throws JspException { . . . // create validator object return validator; } public void release() { // release state super.release(); // set validator properties to null } // setter methods for validator properties }

The createValidator Method
To be able to share the same validator object between different pages, the validator class should be created in the following way.

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>

The Validator Class
public class MyValidator implements Validator, StateHolder { // Custom Validator ID as defined in faces-config.xml file public static String VALIDATOR_ID = CustomValidatorId;
/** The identifier of the error message. */ public static final String MESSAGE_ID = "name of message";

private boolean transientValue = false; // parameters are not transient // implement Validator interface public void validate( FacesContext facesContext, UIComponent uiComponent, Object value) { if (value does not match requirements) { // raise a validator exception FacesMessage message = MessageFactory.getMessage( FacesMessage.SEVERITY_ERROR, MESSAGE_ID, msg.params...); throw new ValidatorException(message); } }
// implement StateHolder interface

public void restoreState(FacesContext fc, Object state) { // read parameters from state } public Object saveState(FacesContext arg0) { // return wrapped parameters in a serializable Object }
// 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

The Directory Structure
The Tag-Library Description files name is arbitrary, as long as it has a *.tld file extension.

56

throw new ValidatorException(message).SEVERITY_ERROR.parseInt(value. Here. /** The identifier of the error message. */ public static final String GREATER_THAN_MESSAGE_ID = "GreaterThanValidator.getValue().9.2 The Greater-Than Validator We implement an example validateGreaterThan tag which compares the values of two components. StateHolder { /** The identifier of the validator. if (Integer. whose value is compared to this component's value: <mytags:validateGreaterThan compareToId="main:age"/> The GreaterThanValidator Class public class GreaterThanValidator implements Validator. UIComponent compareToComponent = uiComponent. Object value) { if (value == null) return.toString())) { // raise a validator exception FacesMessage message = MessageFactory. The validateGreaterThan tag demands a „comparedToId“ attribute to define the (id of the) component. // implement Validator interface public void validate(FacesContext facesContext. // id of component whose value is compared to this components value private String compareToId. if (greaterThanValue == null) return. greaterThanValue). // compareToId is not transient private boolean transientValue = false.parseInt(greaterThanValue. if (compareToComponent instanceof EditableValueHolder) { Object greaterThanValue = ((EditableValueHolder) compareToComponent) .GREATER_THAN_ERROR".getLabel(). ((HtmlInputText) compareToComponent). } } } 57 .getMessage( FacesMessage. */ public static final String VALIDATOR_ID = "GreaterThanValidator". GREATER_THAN_MESSAGE_ID.findComponent(compareToId). UIComponent uiComponent. the value of the age component must be smaller than the value of the mother's age.toString()) <= Integer .

} // return the compareToId public String getCompareToId() { return compareToId. Object state) { compareToId = (String) state. } } 58 .// value holder method public void restoreState(FacesContext fc. } // value holder method public void setTransient(boolean value) { transientValue = value.compareToId = compareToId. } // value holder method public boolean isTransient() { return transientValue. } // store the value of compareToId public void setCompareToId(String compareToId) { this. } // value holder method public Object saveState(FacesContext arg0) { return compareToId.

String cId. GreaterThanValidator validator = (GreaterThanValidator) context .VALIDATOR_ID).getValue(context. public void setCompareToId(ValueExpression compareToId) { this. compareToId = null.createValidator(GreaterThanValidator.getELContext()). validator.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. if (compareToId.setCompareToId(cId).compareToId = compareToId.isLiteralText()) cId = compareToId.getExpressionString(). } public Validator createValidator() throws JspException { FacesContext context = FacesContext. return validator. public class GreaterThanValidatorTag extends ValidatorELTag { // attribute of the tag private ValueExpression compareToId. else cId = (String) compareToId.tld <?xml version="1.getApplication(). } } The Tag Library Description: taglib. } public void release() { super.getCurrentInstance().0" encoding="UTF-8" ?> 59 .release().

<taglib version="2.com/jsf/html" xmlns:g="http://helloWorld/taglib"> .sun.lang.yourAge}" value="#{helloBean.mage}"> <g:validateGreaterThan compareToId="main:age" /> </h:inputText> <h:message for="mothersAge" styleClass="errorMessage" /> . </jsp:root> 10 JSF Custom Components The JSF framework offers a lot of standard components out of the box.age}" required="true" /> <h:message for="age" styleClass="errorMessage" /> <h:outputText value="#{label.1" xmlns:jsp="http://java.String</type> </deferred-value> </attribute> </tag> .com/xml/ns/javaee http://java.com/xml/ns/javaee/web-jsptaglibrary_2_1..mothersAge}" value="#{helloBean...yourAge}" /> <h:inputText id="age" label="#{label.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.w3..sun...mothersAge}" /> <h:inputText id="mothersAge" label="#{label. <h:outputText value="#{label.1" xmlns="http://java.com/jsf/core" xmlns:h="http://java. ... .com/xml/ns/javaee" xmlns:xsi="http://www. <f:view> <h:form id="main"> ..sun.com/JSP/Page" xmlns:f="http://java.sun.xsd"> <tlib-version>1.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. </taglib> The custom tag can then be used in the JSP page like this: <jsp:root version="2.sun. The JSF component model 60 .0</tlib-version> <short-name>myTags</short-name> <uri>http://helloWorld/taglib</uri> <tag> <name>validateGreaterThan</name> <tag-class>helloWorld.sun.

tree view) • support functionality for other markup languages (e. If a component defines properties. But the development of custom components requires special expertise.g. it must implement the StateHolder interface to save and restore them. file upload) • provide additional functionality (e. 61 .2 Component Data Collections Components have three types of data collections: • attributes which are untyped key/value pairs • value expressions which define bindings to backing bean properties • individual properties with corresponding setter and getter methods The put() and get() methods of the attributes indirectly access the properties and value expressions if available. Writing a custom component is necessary if you want • to support special HTML features (e.and the extensible architecture allow to create new components. progress bar) 10. sortable data table) • create new types of components (e.g.1 The Component Hierarchy StateHolder ValueHolder Editable ValueHolder UIComponent Base id parent children attributes valueExpressions encodeBegin() encodeChildren() encodeEnd() saveState() restoreState() UIOutput localValue value converter UIInput submittedValue validators decode() updateModel() 10.g.g.

10. the local value or the value of the associated backing bean property Values during Request Processing PROCESS VALIDATIONS 2: validate() 2a: setValue() 2b: clearSubmittedValue() APPLY REQUEST VALUES 1: decode() 1a: setSubmittedValue() Input Component 3b: setProperty() 5c: getProperty() Backing Bean UPDATE MODEL VALUES 3: updateModel() 3a: getLocalValue() 3c: clearValue() RENDER RESPONSE 5: encodeBegin() 5a: getSubmittedValue() 5b: getValue() INVOKE APPLICAION 4: action() 62 .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 following steps are needed: 1. Implement the component class by subclassing an appropriate base class (e.10.4 Example of a Custom Component In order to develop a custom UI component. <h:commandButton value="#{label.xml) 3.g. 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> . UIComponent Base UIComponent ELTag Custom Component uses Custom ComponentTag registers JSF Configuration registers Tag Library Descriptor In this example a custom input component is developed which allows a user to select a number within a range of numbers. i.sayHello}" /> </h:from> 63 .age}" /> . implement a custom tag (tag handler class..e.age}" /> <g:selectNumber id="helloAge" min="1" max="50" value="#{helloBean.. Integrate the class with JSP.. tag library descriptor). Register the class in the JSF application configuration file (faces-config.. <h:outputText value="#{label.hello}" action="#{helloBean. UIInput) 2.

get("number"). val++) { writer. val <= max.startElement("option". ResponseWriter writer = context. "number". for (int val = min. setSubmittedValue(value). writer.get("max"). if (getValue().endElement("option").writeAttribute("name". Integer max = (Integer)getAttributes(). "true". */ public void encodeBegin(FacesContext context) throws IOException { Integer min = (Integer)getAttributes(). writer. writer. val. this).writeText(val. encodeChildren() and encodeEnd().startElement("select". UIInput) • defines its type as a constant (COMPONENT_TYPE) • sets its renderer type (not necessary for simple components) • defines its family which is used to find an appropriate renderer (usually inherited from the base class) • implements the methods encodeBegin(). which are called in order to render a component • implements the decode() method. this). */ public static final String COMPONENT_TYPE = "SelectNumber".endElement("select"). } writer. writer. null). } /** Decodes the selected number from the request.equals(val)) writer. null). which interprets browser input and sets the submitted value of the component public class SelectNumber extends UIInput { /** The identifier of the component. */ /** Sets the renderer type.getResponseWriter(). writer.The Component Class: SelectNumber The component class • subclasses an appropriate base class (e.getRequestParameterMap().writeAttribute("selected". } } 64 .g. null). } /** Renders the number selection to the response. String value = params. public SelectNumber() { setRendererType(null).writeAttribute("value". String> params = context.get("min"). null).getExternalContext(). */ public void decode(FacesContext context) { Map<String.

*/ private ValueExpression value.. . public String getComponentType() { return SelectNumber. */ .HelloBean</managed-bean-class> <managed-bean-scope>session</managed-bean-scope> </managed-bean> . </faces-config> The Component Tag Handler Class: SelectNumberTag The component tag handler class is derived from the UIComponentELTag class. <component> <component-type>SelectNumber</component-type> <component-class>helloWorld. } 65 /** Returns the component type. and value).0' encoding='UTF-8'?> <faces-config version="1. the tag handler class has to define corresponding properties (here min. the component has to be declared by specifying its type and its implementation class <?xml version='1. max. */ private String min. /** The maximum value. . > <managed-bean> <description>The one and only HelloBean.COMPONENT_TYPE. . If the component has attributes or properties which should be exposed as tag attributes. We need setter methods as well as a release method for those properties. private String max.2" xmlns="http://java..The Configuration File: faces-config. */ /** The value binding.xml In the application configuration file. The setProperties() method maps the properties of the tag class to attributes or value expressions of the component public class SelectNumberTag extends UIComponentELTag { /** The minimum value.</description> <managed-bean-name>helloBean</managed-bean-name> <managed-bean-class>helloWorld. The component tag handler associates the tag with a component and with a renderer (if the component does not render itself).com/xml/ns/javaee" .SelectNumber</component-class> </component> .sun. ..

isLiteralText()) component. if (value. min = max = null.value = value.put("value".getAttributes(). } 66 .setValueExpression("value". } public void setMax(String max) { this. value. value).getAttributes(). } /** Sets the maximum value. new Integer(min)).put("max".max = max.put("min". component.min = min. } public void setProperties(UIComponent component) { super. component.setProperties(component).getAttributes(). value = null.release(). */ public void setMin(String min) { this.getExpressionString()). } /** Sets the minimum value. } /** Sets the properties of the component. else component. */ } public void release() { super./** Returns the renderer type. */ public String getRendererType() { return null. */ public void setValue(ValueExpression value) { this. */ /** Sets the value binding. */ /** Releases the resources. new Integer(max)).

1" xmlns:f="http://java.w3.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. min.com/jsf/core" xmlns:h="http://java.sun.The Tag Library Descriptor: taglib. <jsp:root xmlns:jsp="http://java. <?xml version="1.number}"/> <h:commandButton value="Submit"/> </h:form> </f:view> </html> </jsp:root> 67 .tld The tag library descriptor (TLD) groups different JSP tags into a tag library which is identified by a URI.sun.com/JSP/Page" version="2.lang.1</tlib-version> <short-name>myTags</short-name> <uri>http://helloWorld/taglib</uri> <tag> <name>selectNumber</name> <tag-class>helloWorld.org/1999/xhtml"> <f:view> <h:form> <g:selectNumber min="1" max="10" value="#{helloBean.SelectNumberTag) and defines the valid tag attributes (max.Integer</type> </deferred-value> </attribute> </tag> </taglib> The JSP page: index. A tag description maps a tag name (here selectNumber) to a tag handler class (here helloWorld. the URI of the tag library has to be defined as XML namespace of the tag element.sun.0"?> <taglib . value and id).jsp In the JSP page.com/jsf/html" xmlns:g="http://helloWorld/taglib"> <jsp:directive. > <tlib-version>1. .page contentType="text/html"/> <html xmlns="http://www. .

.war index.xml taglib..jsp .xml faces-config.xml /WEB-INF/classes .class Summary of Select Number Example 68 ... /WEB-INF/lib jsf-component. /WEB-INF web.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.class SelectNumberTag.jar /META-INF faces-config.jar jsf-component.tld /jsf/examples SelectNumber.

Sign up to vote on this title
UsefulNot useful