Specification: Jakarta Faces

Version: 4.0

Status: Final

Release: May 16, 2022

Copyright © 2019, 2022 Eclipse Foundation. https://www.eclipse.org/legal/efsl.php

Eclipse Foundation Specification License – v1.0

By using and/or copying this document, or the Eclipse Foundation document from which this statement is linked, you (the licensee) agree that you have read, understood, and will comply with the following terms and conditions:

Permission to copy, and distribute the contents of this document, or the Eclipse Foundation document from which this statement is linked, in any medium for any purpose and without fee or royalty is hereby granted, provided that you include the following on ALL copies of the document, or portions thereof, that you use:

  • link or URL to the original Eclipse Foundation document.

  • All existing copyright notices, or if one does not exist, a notice (hypertext is preferred, but a textual representation is permitted) of the form: "Copyright (c) 2019, [$date-of-document] Eclipse Foundation, Inc. <<url to this license>>"

Inclusion of the full text of this NOTICE must be provided. We request that authorship attribution be provided in any software, documents, or other items or products that you create pursuant to the implementation of the contents of this document, or any portion thereof.

No right to create modifications or derivatives of Eclipse Foundation documents is granted pursuant to this license, except anyone may prepare and distribute derivative works and portions of this document in software that implements the specification, in supporting materials accompanying such software, and in documentation of such software, PROVIDED that all such works include the notice below. HOWEVER, the publication of derivative works of this document for use as a technical specification is expressly prohibited.

The notice is:

"Copyright (c) 2019, [$date-of-document] Eclipse Foundation. This software or document includes material copied from or derived from [title and URI of the Eclipse Foundation specification document]."

Disclaimers

THIS DOCUMENT IS PROVIDED "AS IS," AND THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION MAKE NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS OF THE DOCUMENT ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE IMPLEMENTATION OF SUCH CONTENTS WILL NOT INFRINGE ANY THIRD PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.

THE COPYRIGHT HOLDERS AND THE ECLIPSE FOUNDATION WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF ANY USE OF THE DOCUMENT OR THE PERFORMANCE OR IMPLEMENTATION OF THE CONTENTS THEREOF.

The name and trademarks of the copyright holders or the Eclipse Foundation may NOT be used in advertising or publicity pertaining to this document or its contents without specific, written prior permission. Title to copyright in this document will at all times remain with copyright holders.

Preface

This is the Jakarta Faces Specification Document, version 4.0.

Other Jakarta Platform Specifications

Jakarta Faces 4.0 is based on the following Jakarta specifications:

Jakarta Servlet, version 6.0 https://jakarta.ee/specifications/servlet/

Jakarta Expression Language, version 5.0 https://jakarta.ee/specifications/expression-language/

Jakarta Contexts and Dependency Injection, version 4.0 https://jakarta.ee/specifications/cdi/

Jakarta Bean Validation, version 3.0 https://jakarta.ee/specifications/bean-validation/

Jakarta Tags, version 2.0 https://jakarta.ee/specifications/tags/

Jakarta WebSocket, version 2.0, optional https://jakarta.ee/specifications/websocket/

Jakarta JSON Processing, version 2.1, optional https://jakarta.ee/specifications/jsonp/

Therefore, a Jakarta Faces container must support all of the above specifications. This requirement allows faces applications to be portable across a variety of Jakarta Faces implementations.

In addition, Jakarta Faces is designed to work synergistically with other web-related Java APIs, including:

Portlet Specification 1.0, JSR-168 https://jcp.org/en/jsr/detail?id=168

Portlet Specification 2.0, JSR-286 https://jcp.org/en/jsr/detail?id=286

Portlet Specification 3.0, JSR-362 https://jcp.org/en/jsr/detail?id=362

Portlet Bridge Specification, JSR-301 https://jcp.org/en/jsr/detail?id=301

The following documents and specifications of the World Wide Web Consortium will be of interest to Jakarta Faces implementors, as well as developers of applications and components based on Jakarta Faces.

Hypertext Markup Language (HTML), Living Standard https://html.spec.whatwg.org/

Extensible HyperText Markup Language (XHTML), version 1.0 https://www.w3.org/TR/xhtml1/

Extensible Markup Language (XML), version 1.0 (Second Edition) https://www.w3.org/TR/REC-xml/

The class and method Javadoc documentation for the classes and interfaces in jakarta.faces (and its subpackages) are incorporated by reference as requirements of this Specification.

The Facelet tag library for the HTML_BASIC standard RenderKit is specified in the VDLDocs and incorporated by reference in this Specification.

Terminology

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, MAY, and OPTIONAL in this document are to be interpreted as described in

Key words for use in RFCs to Indicate Requirement Levels (RFC 2119) https://www.rfc-editor.org/rfc/rfc2119.txt

Providing Feedback

We welcome any and all feedback about this specification. Please email your comments to <faces-dev@eclipse.org>.

Please note that, due to the volume of feedback that we receive, you will not normally receive a reply from an engineer. However, each and every comment is read, evaluated, and archived by the specification team.

Acknowledgements

The authors would like to thank the Jakarta Faces 4.0 contributors.

  • Arjan Tijms

  • Bauke Scholtz

  • Thomas Andraschko

  • Manfred Riem

  • Christoph Straßer

  • Emil Lefkof

The editors would like to recognize the following individuals who have contributed to the success of Jakarta Faces over the years.

Ed Burns

Frank Caputo

Cagatay Civici

Ken Fyten

Neil Griffin

Josh Juneau

Brian Leatham

Kito Mann

Michael Müller

Paul Nicolucci

Leonardo Uribe

Dan Allen

Thomas Asel

Jennifer Ball

Lincoln Baxter III

Hans Bergsten

Shawn Bayern

Joseph Berkovitz

Dennis Byrne

Pete Carapetyan

Ryan DeLaplante

Keith Donald

Jim Driscoll

Hanspeter Duennenberger

Ken Finnigan

Amy Fowler

Mike Freedman

David Geary

Manfred Geiler

Ted Goddard

Juan Gonzalez

Jeremy Grelle

Rick Hightower

Jacob Hookom

Justyna Horwat

Alexander Jesse

Max Katz

Roger Keays

Gavin King

Roger Kitain

Eric Lazarus

Jason Lee

Felipe Leme

Cody Lerum

Alberto Lemos

Ryan Lubke

Barbara Louis

Martin Marinschek

Kumar Mettu

Craig McClanahan

Pete Muir

Bernd Müller

Michael Müller

Hans Muller

Brendan Murray

Michael Nash

Imre Osswald

Joe Ottinger

Ken Paulsen

Dhiru Pandey

Raj Premkumar

Werner Punz

Matt Raible

Hazem Saleh

Andy Schwartz

Yara Senger

Stan Silvert

Vernon Singleton

Bernhard Slominski

Alexander Smirnov

Thomas Spiegel

Kyle Stiemann

James Strachan

Jayashri Visvanathan

Ana von Klopp

Matthias Wessendorf

Adam Winer

Mike Youngstrom

John Zukowski

1. Overview

Jakarta Faces is a user interface (UI) framework for Java web applications. It is designed to significantly ease the burden of writing and maintaining applications that run on a Java application server and render their UIs back to a target client. Jakarta Faces provides ease-of-use in the following ways:

  • Makes it easy to construct a UI from a set of reusable UI components

  • Simplifies migration of application data to and from the UI

  • Helps manage UI state across server requests

  • Provides a simple model for wiring client-generated events to server-side application code

  • Allows custom UI components to be easily built and re-used

Most importantly, Jakarta Faces establishes standards which are designed to be leveraged by tools to provide a developer experience which is accessible to a wide variety of developer types, ranging from corporate developers to systems programmers. A “corporate developer” is characterized as an individual who is proficient in writing procedural code and business logic, but is not necessarily skilled in object-oriented programming. A “systems programmer” understands object-oriented fundamentals, including abstraction and designing for re-use. A corporate developer typically relies on tools for development, while a system programmer may define his or her tool as a text editor for writing code.

Therefore, Jakarta Faces is designed to be tooled, but also exposes the framework and programming model as APIs so that it can be used outside of tools, as is sometimes required by systems programmers.

1.1. Solving Practical Problems of the Web

Jakarta Faces’s core architecture is designed to be independent of specific protocols and markup. However it is also aimed directly at solving many of the common problems encountered when writing applications for HTML clients that communicate via HTTP to a Java application server that supports Jakarta Servlet and Jakarta Server Pages based applications. These applications are typically form-based, and are comprised of one or more HTML pages with which the user interacts to complete a task or set of tasks. Jakarta Faces tackles the following challenges associated with these applications:

  • Managing UI component state across requests

  • Supporting encapsulation of the differences in markup across different browsers and clients

  • Supporting form processing (multi-page, more than one per page, and so on)

  • Providing a strongly typed event model that allows the application to write server-side handlers (independent of HTTP) for client generated events

  • Validating request data and providing appropriate error reporting

  • Enabling type conversion when migrating markup values (Strings) to and from application data objects (which are often not Strings)

  • Handling error and exceptions, and reporting errors in human-readable form back to the application user

  • Handling page-to-page navigation in response to UI events and model interactions.

1.2. Specification Audience

The Jakarta Faces Specification, and the technology that it defines, is addressed to several audiences that will use this information in different ways. The following sections describe these audiences, the roles that they play with respect to Jakarta Faces, and how they will use the information contained in this document. As is the case with many technologies, the same person may play more than one of these roles in a particular development scenario; however, it is still useful to understand the individual viewpoints separately.

1.2.1. Page Authors

A page author is primarily responsible for creating the user interface of a web application. He or she must be familiar with the markup and scripting languages (such as HTML and JavaScript) that are understood by the target client devices, as well as the rendering technology (such as Facelets) used to create dynamic content. Page authors are often focused on graphical design and human factors engineering, and are generally not familiar with programming languages such as Java or Visual Basic (although many page authors will have a basic understanding of client side scripting languages such as JavaScript).

Page authors will generally assemble the content of the pages being created from libraries of prebuilt user interface components that are provided by component writers, tool providers, and Jakarta Faces implementors. The components themselves will be represented as configurable objects that utilize the dynamic markup capabilities of the underlying rendering technology. When Facelets are in use, for example, Jakarta Faces components will be represented as namespaced tags, which will support configuring the attributes of those components as tag attributes in the page. In addition, the pages produced by a page author will be used by the Jakarta Faces framework to create component tree hierarchies, called “views”, that represent the components on those pages.

Page authors will generally utilize development tools, such as HTML editors, that allow them to deal directly with the visual representation of the page being created. However, it is still feasible for a page author that is familiar with the underlying rendering technology to construct pages “by hand” using a text editor.

1.2.2. Component Writers

Component writers are responsible for creating libraries of reusable user interface objects. Such components support the following functionality:

  • Convert the internal representation of the component’s properties and attributes into the appropriate markup language for pages being rendered (encoding).

  • Convert the properties of an incoming request—parameters, headers, and cookies—into the corresponding properties and attributes of the component (decoding)

  • Utilize request-time events to initiate visual changes in one or more components, followed by redisplay of the current page.

  • Support validation checks on the syntax and semantics of the representation of this component on an incoming request, as well as conversion into the internal form that is appropriate for this component.

  • Saving and restoring component state across requests

As will be discussed in Rendering Model, the encoding and decoding functionality may optionally be delegated to one or more Render Kits, which are responsible for customizing these operations to the precise requirements of the client that is initiating a particular request (for example, adapting to the differences between JavaScript handling in different browsers, or variations in the WML markup supported by different wireless clients).

The component writer role is sometimes separate from other Jakarta Faces roles, but is often combined. For example, reusable components, component libraries, and render kits might be created by:

  • A page author creating a custom “widget” for use on a particular page

  • An application developer providing components that correspond to specific data objects in the application’s business domain

  • A specialized team within a larger development group responsible for creating standardized components for reuse across applications

  • Third party library and framework providers creating component libraries that are portable across Jakarta Faces implementations

  • Tool providers whose tools can leverage the specific capabilities of those libraries in development of Jakarta Faces-based applications

  • Jakarta Faces implementors who provide implementation-specific component libraries as part of their Jakarta Faces product suite

Within Jakarta Faces, user interface components are represented as Java classes that follow the design patterns outlined in the JavaBeans Specification. Therefore, new and existing tools that facilitate JavaBean development can be leveraged to create new Jakarta Faces components. In addition, the fundamental component APIs are simple enough for developers with basic Java programming skills to program by hand.

1.2.3. Application Developers

Application Developers are responsible for providing the server-side functionality of a web application that is not directly related to the user interface. This encompasses the following general areas of responsibility:

  • Define mechanisms for persistent storage of the information required by Jakarta Faces-based web applications (such as creating schemas in a relational database management system)

  • Create a Java object representation of the persistent information, such as Jakarta Persistence entities, and call the corresponding beans as necessary to perform persistence of the application’s data.

  • Encapsulate the application’s functionality, or business logic, in Java objects that are reusable in web and non-web applications, such as CDI beans.

  • Expose the data representation and functional logic objects for use via Jakarta Faces, as would be done for any Jakarta Servlet- or Jakarta Server Pages-based application.

Only the latter responsibility is directly related to Jakarta Faces APIs. In particular, the following steps are required to fulfill this responsibility:

  • Expose the underlying data required by the user interface layer as objects that are accessible from the web tier (such as via request or session attributes in the Jakarta Servlet API), via value reference expressions, as described in Standard User Interface Components.”

  • Provide application-level event handlers for the events that are enqueued by Jakarta Faces components during the request processing lifecycle, as described in Invoke Application.

Application modules interact with Jakarta Faces through standard APIs, and can therefore be created using new and existing tools that facilitate general Java development. In addition, application modules can be written (either by hand, or by being generated) in conformance to an application framework created by a tool provider.

1.2.4. Tool Providers

Tool providers, as their name implies, are responsible for creating tools that assist in the development of Jakarta Faces-based applications, rather than creating such applications directly. Jakarta Faces APIs support the creation of a rich variety of development tools, which can create applications that are portable across multiple Jakarta Faces implementations. Examples of possible tools include:

  • GUI-oriented page development tools that assist page authors in creating the user interface for a web application

  • IDEs that facilitate the creation of components (either for a particular page, or for a reusable component library)

  • Page generators that work from a high level description of the desired user interface to create the corresponding page and component objects

  • IDEs that support the development of general web applications, adapted to provide specialized support (such as configuration management) for Jakarta Faces

  • Web application frameworks (such as MVC-based and workflow management systems) that facilitate the use of Jakarta Faces components for user interface design, in conjunction with higher level navigation management and other services

  • Application generators that convert high level descriptions of an entire application into the set of pages, UI components, and application modules needed to provide the required application functionality

Tool providers will generally leverage the Jakarta Faces APIs for introspection of the features of component libraries and render kit frameworks, as well as the application portability implied by the use of standard APIs in the code generated for an application.

1.2.5. Jakarta Faces Implementors

Finally, Jakarta Faces implementors will provide runtime environments that implement all of the requirements described in this specification. Typically, a Jakarta Faces implementor will be the provider of a Jakarta EE application server, although it is also possible to provide a Jakarta Faces implementation that is portable across Jakarta EE servers.

Advanced features of the Jakarta Faces APIs allow Jakarta Faces implementors, as well as application developers, to customize and extend the basic functionality of Jakarta Faces in a portable way. These features provide a rich environment for server vendors to compete on features and quality of service aspects of their implementations, while maximizing the portability of Jakarta Faces-based applications across different Jakarta Faces implementations.

1.3. Introduction to Jakarta Faces APIs

This section briefly describes major functional subdivisions of the APIs defined by Jakarta Faces. Each subdivision is described in its own chapter, later in this specification.

1.3.1. package jakarta.faces

This package contains top level classes for the Jakarta Faces API. The most important class in the package is FactoryFinder, which is the mechanism by which users can override many of the key pieces of the implementation with their own.

Please see FactoryFinder.

1.3.2. package jakarta.faces.application

This package contains APIs that are used to link an application’s business logic objects to Jakarta Faces, as well as convenient pluggable mechanisms to manage the execution of an application that is based on Jakarta Faces. The main class in this package is Application.

Please see Application.

1.3.3. package jakarta.faces.component

This package contains fundamental APIs for user interface components.

1.3.4. package jakarta.faces.component.html

This package contains concrete base classes for each valid combination of component + renderer.

1.3.5. package jakarta.faces.context

This package contains classes and interfaces defining per-request state information. The main class in this package is FacesContext, which is the access point for all per-request information, as well as the gateway to several other helper classes.

Please see FacesContext.

1.3.6. package jakarta.faces.convert

This package contains classes and interfaces defining converters. The main class in this package is Converter.

Please see Conversion Model.

1.3.7. package jakarta.faces.el

This package contains an interface for the Composite Component Attributes ELResolver.

1.3.8. package jakarta.faces.flow and jakarta.faces.flow.builder

The runtime API for Faces Flows.

Please see FlowHandler.

1.3.9. package jakarta.faces.lifecycle

This package contains classes and interfaces defining lifecycle management for the Jakarta Faces implementation. The main class in this package is Lifecycle. Lifecycle is the gateway to executing the request processing lifecycle.

1.3.10. package jakarta.faces.event

This package contains interfaces describing events and event listeners, and concrete event implementation classes. All component-level events extend from FacesEvent and all component-level listeners extend from FacesListener.

1.3.11. package jakarta.faces.render

This package contains classes and interfaces defining the rendering model. The main class in this package is RenderKit. RenderKit maintains references to a collection of Renderer instances which provide rendering capability for a specific client device type.

Please see Rendering Model.

1.3.12. package jakarta.faces.validator

Interface defining the validator model, and concrete validator implementation classes.

Please see Validation Model

1.3.13. package jakarta.faces.webapp

A standard Jakarta Servlet class required for integration of Jakarta Faces into web applications.

2. Request Processing Lifecycle

Web user interfaces generally follow a pattern where the user-agent sends one or more requests to the server with the end goal of displaying a user-interface. In the case of Web browsers, an initial HTTP GET or POST request is made to the server, which responds with a document which the browser interprets and automatically makes subsequent requests on the user’s behalf. The responses to each of these subsequent requests are usually images, JavaScript files, CSS Style Sheets, and other artifacts that fit “into” the original document. If the Jakarta Faces lifecycle is involved in rendering the initial response, the entire process of initial request, the response to that request, and any subsequent requests made automatically by the user-agent, and their responses, is called a Faces View Request/Response for discussion. The following graphic illustrates a Faces View Request/Response.

Faces View Request/Response Lifecycle

Each Faces View Request/Response goes through a well-defined request processing lifecycle made up of phases. There are three different scenarios that must be considered, each with its own combination of phases and activities:

  • Non-Faces Request generates Faces Response

  • Faces Request generates Faces Response

  • Faces Request generates Non-Faces Response

Where the terms being used are defined as follows:

  • Faces Response —A response that was created by the execution of the Render Response phase of the request processing lifecycle.

  • Non-Faces Response —A response that was not created by the execution of the render response phase of the request processing lifecycle. Examples would be a Jakarta Servlet-generated or Jakarta Server Pages-rendered response that does not incorporate Jakarta Faces components, a response that sets an HTTP status code other than the usual 200 (such as a redirect), or a response whose HTTP body consists entirely of the bytes of an in page resource, such as a JavaScript file, a CSS file, an image, or an applet. This last scenario is considered a special case of a Non-Faces Response and will be referred to as a Faces Resource Response for the remainder of this specification.

  • Faces Request —A request that was sent from a previously generated Faces response. Examples would be a hyperlink or form submit from a rendered user interface component, where the request URI was crafted (by the component or renderer that created it) to identify the view to use for processing the request. Another example is a request for a resource that the user-agent was instructed to fetch an artifact such as an image, a JavaScript file, a CSS stylesheet, or an applet. This last scenario is considered a special case of a Faces Request and will be referred to as a Faces Resource Request for the remainder of this specification.

  • Non-Faces Request —A request that was sent to an application component (e.g. a Jakarta Servlet or Jakarta Server Pages page), rather than directed to a Faces view.

In addition, of course, your web application may receive non-Faces requests that generate non-Faces responses. Because such requests do not involve Jakarta Faces at all, their processing is outside the scope of this specification, and will not be considered further.

READER NOTE: The dynamic behavior descriptions in this Chapter make forward references to the sections that describe the individual classes and interfaces. You will probably find it useful to follow the reference and skim the definition of each new class or interface as you encounter them, then come back and finish the behavior description. Later, you can study the characteristics of each Jakarta Faces API in the subsequent chapters.

2.1. Request Processing Lifecycle Scenarios

Each of the scenarios described above has a lifecycle that is composed of a particular set of phases, executed in a particular order. The scenarios are described individually in the following subsections.

2.1.1. Non-Faces Request Generates Faces Response

An application that is processing a non-Faces request may use Jakarta Faces to render a Faces response to that request. In order to accomplish this, the application must perform the common activities that are described in the following sections:

2.1.2. Faces Request Generates Faces Response

The most common lifecycle will be the case where a previous Faces response includes user interface controls that will submit a subsequent request to this web application, utilizing a request URI that is mapped to the Jakarta Faces implementation’s controller, as described in Servlet Mapping. Because such a request will be initially handled by the Jakarta Faces implementation, the application need not take any special steps—its event listeners, validators, and application actions will be invoked at appropriate times as the standard request processing lifecycle, described in the following diagrams, is invoked.

Faces Resource Request Lifecycle

The “Handle Resource Request” box, and its subsequent boxes, are explained in Resource Handling. The following diagram explains the “Execute and Render Lifecycle” box.

Faces Execute and Render Lifecycle

The behavior of the individual phases of the request processing lifecycle are described in individual subsections of Standard Request Processing Lifecycle Phases. Note that, at the conclusion of several phases of the request processing lifecycle, common event processing logic (as described in Common Event Processing) is performed to broadcast any FacesEvents generated by components in the component tree to interested event listeners.

2.1.3. Faces Request Generates Non-Faces Response

Normally, a Jakarta Faces-based application will utilize the Render Response phase of the request processing lifecycle to actually create the response that is sent back to the client. In some circumstances, however, this behavior might not be desirable. For example:

  • A Faces Request needs to be redirected to a different web application resource (via a call to HttpServletResponse.sendRedirect).

  • A Faces Request causes the generation of a response using some other technology (such as a Jakarta Servlet, or a Jakarta Server Pages page not containing Jakarta Faces components).

  • A Faces Request causes the generation of a response simply by serving up the bytes of a resource, such as an image, a JavaScript file, a CSS file, or an applet

In any of these scenarios, the application will have used the standard mechanisms of the Jakarta Servlet or Portlet API to create the response headers and content. It is then necessary to tell the Jakarta Faces implementation that the response has already been created, so that the Render Response phase of the request processing lifecycle should be skipped. This is accomplished by calling the responseComplete() method on the FacesContext instance for the current request, prior to returning from event handlers or application actions.

2.2. Standard Request Processing Lifecycle Phases

The standard phases of the request processing lifecycle are described in the following subsections.

The default request lifecycle processing implementation must ensure that the currentPhaseId property of the FacesContext instance for this request is set with the proper PhaseId constant for the current phase as early as possible at the beginning of each phase.

2.2.1. Restore View

The Jakarta Faces implementation must perform the following tasks during the Restore View phase of the request processing lifecycle:

  • Call initView() on the ViewHandler. This will set the character encoding properly for this request.

  • Examine the FacesContext instance for the current request. If it already contains a UIViewRoot:

    • Set the locale on this UIViewRoot to the value returned by the getRequestLocale() method on the ExternalContext for this request.

    • Take no further action during this phase, and return. The presence of a UIViewRoot already installed in the FacesContext before the Restore View Phase implementation indicates that the phase should assume the view has already been restored by other means.

  • Derive the viewId according to the following algorithm, or one semantically equivalent to it.

    • Look in the request map for a value under the key jakarta.servlet.include.path_info. If found, let it be the viewId.

    • Call getRequestPathInfo() on the current ExternalContext. If this value is non-null, let this be the viewId .

    • Look in the request map for a value under the key jakarta.servlet.include.servlet_path. If found, let it be the viewId.

    • If none of these steps yields a non-null viewId, throw a FacesException with an appropriate localized message.

  • Determine if this request is a postback or initial request by executing the following algorithm. Find the render-kit-id for the current request by calling calculateRenderKitId() on the Application’s ViewHandler. Get that RenderKit’s ResponseStateManager and call its isPostback() method, passing the current FacesContext. If the current request is an attempt by the servlet container to display a servlet error page, do not interpret the request as a postback, even if it is indeed a postback.

  • If the request is a postback, call setProcessingEvents(false) on the current FacesContext. Then call ViewHandler.restoreView(), passing the FacesContext instance for the current request and the view identifier, and returning a UIViewRoot for the restored view. If the return from ViewHandler.restoreView() is null, throw a ViewExpiredException with an appropriate error message. jakarta.faces.application.ViewExpiredException is a FacesException that must be thrown to signal to the application that the expected view was not returned for the view identifier. An application may choose to perform some action based on this exception.

  • Store the restored UIViewRoot in the FacesContext.

  • Call setProcessingEvents(true) on the current FacesContext.

  • If the request is not a postback, try to obtain the ViewDeclarationLanguage from the ViewHandler, for the current viewId by calling ViewHandler.deriveLogicalViewId() and passing the result to ViewHandler.getViewDeclarationLanguage(). If no such instance can be obtained, call facesContext.renderResponse(). Otherwise, call getViewMetadata() on the ViewDeclarationLanguage instance. If the result is non-null, call createMetadataView() on the ViewMetadata instance. Call ViewMetadata.hasMetadata(), passing the newly created viewRoot. If this method returns false, call facesContext.renderResponse(). If it turns out that the previous call to createViewMetadata() did not create a UIViewRoot instance, call createView() on the ViewHandler.

View Protection
  • Call ViewHandler.getProtectedViewsUnmodifiable() to determine if the view for this viewId is protected. If not, assume the requested view is not protected and take no additional view protection steps. Obtain the value of the value of the request parameter whose name is given by the value of ResponseStateManager.NON_POSTBACK_VIEW_TOKEN_PARAM. If there is no value, throw ProtectedViewException. If the value is present, compare it to the return from ResponseStateManager.getCryptographicallyStrongTokenFromSession(). If the values do not match, throw ProtectedViewException. If the values do match, look for a Referer [sic] request header. If the header is present, use the protected view API to determine if any of the declared protected views match the value of the Referer header. If so, conclude that the previously visited page is also a protected view and it is therefore safe to continue. Otherwise, try to determine if the value of the Referer header corresponds to any of the views in the current web application. If not, throw a ProtectedViewException. If the Origin header is present, additionally perform the same steps as with the Referer header.

  • Call renderResponse() on the FacesContext .

Obtain a reference to the FlowHandler from the Application. Call its clientWindowTransition() method. This ensures that navigation that happened as a result of the renderer for the jakarta.faces.OutcomeTarget component-family is correctly handled with respect to flows. For example, this enables <h:button> to work correctly with flows.

Using Application.publishEvent(), publish a PostAddToViewEvent with the created UIViewRoot as the event source.

In all cases, the implementation must ensure that the restored tree is traversed and the PostRestoreStateEvent is published for every node in the tree.

At the end of this phase, the viewRoot property of the FacesContext instance for the current request will reflect the saved configuration of the view generated by the previous Faces Response, or a new view returned by ViewHandler.createView() for the view identifier.

2.2.2. Apply Request Values

The purpose of the Apply Request Values phase of the request processing lifecycle is to give each component the opportunity to update its current state from the information included in the current request (parameters, headers, cookies, and so on). When the information from the current request has been examined to update the component’s current state, the component is said to have a “local value”.

During the Apply Request Values phase, the Jakarta Faces implementation must call the processDecodes() method of the UIViewRoot of the component tree. This will normally cause the processDecodes() method of each component in the tree to be called recursively, as described in the Javadocs for the UIComponent.processDecodes() method. The processDecodes() method must determine if the current request is a “partial request” by calling FacesContext.getCurrentInstance().getPartialViewContext().isPartialRequest() . If FacesContext.getCurrentInstance().getPartialViewContext().isPartialRequest() returns true, perform the sequence of steps as outlined in Apply Request Values Partial Processing. Details of the decoding process follow.

During the decoding of request values, some components perform special processing, including:

  • Components that implement ActionSource (such as UICommand), which recognize that they were activated, will queue an ActionEvent. The event will be delivered at the end of Apply Request Values phase if the immediate property of the component is true, or at the end of Invoke Application phase if it is false.

  • Components that implement EditableValueHolder (such as UIInput), and whose immediate property is set to true, will cause the conversion and validation processing (including the potential to fire ValueChangeEvent events) that normally happens during Process Validations phase to occur during Apply Request Values phase instead.

As described in Common Event Processing, the processDecodes() method on the UIViewRoot component at the root of the component tree will have caused any queued events to be broadcast to interested listeners.

At the end of this phase, all EditableValueHolder components in the component tree will have been updated with new submitted values included in this request (or enough data to reproduce incorrect input will have been stored, if there were conversion errors). In addition, conversion and validation will have been performed on EditableValueHolder components whose immediate property is set to true, as described in the UIInput Javadocs. Conversions and validations that failed will have caused messages to be enqueued via calls to the addMessage() method of the FacesContext instance for the current request, and the valid property on the corresponding component(s) will be set to false.

If any of the decode() methods that were invoked, or an event listener that processed a queued event, called responseComplete() on the FacesContext instance for the current request, clear the remaining events from the event queue and terminate lifecycle processing of the current request. If any of the decode() methods that were invoked, or an event listener that processed a queued event, called renderResponse() on the FacesContext instance for the current request, clear the remaining events from the event queue and transfer control to the Render Response phase of the request processing lifecycle. Otherwise, control must proceed to the Process Validations phase.

2.2.2.1. Apply Request Values Partial Processing

Call FacesContext.getPartialViewContext(). Call PartialViewContext.processPartial() passing the FacesContext, PhaseID.APPLY_REQUEST_VALUES as arguments.

2.2.3. Process Validations

As part of the creation of the view for this request, zero or more Validator instances may have been registered for each component. In addition, component classes themselves may implement validation logic in their validate() methods.

During the Process Validations phase of the request processing lifecycle, the Jakarta Faces implementation must call the processValidators() method of the UIViewRoot of the tree. This will normally cause the processValidators() method of each component in the tree to be called recursively, as described in the API reference for the UIComponent.processValidators() method. The processValidators() method must determine if the current request is a “partial request” by calling FacesContext.getCurrentInstance().getPartialViewContext().isPartialRequest() . If FacesContext.getCurrentInstance().getPartialViewContext().isPartialRequest() returns true, perform the sequence of steps as outlined in Partial Validations Partial Processing. Note that EditableValueHolder components whose immediate property is set to true will have had their conversion and validation processing performed during Apply Request Values phase.

During the processing of validations, events may have been queued by the components and/or Validators whose validate() method was invoked. As described in Common Event Processing, the processValidators() method on the UIViewRoot component at the root of the component tree will have caused any queued events to be broadcast to interested listeners.

At the end of this phase, all conversions and configured validations will have been completed. Conversions and Validations that failed will have caused messages to be enqueued via calls to the addMessage() method of the FacesContext instance for the current request, and the valid property on the corresponding components will have been set to false.

If any of the validate() methods that were invoked, or an event listener that processed a queued event, called responseComplete() on the FacesContext instance for the current request, clear the remaining events from the event queue and terminate lifecycle processing of the current request. If any of the validate() methods that were invoked, or an event listener that processed a queued event, called renderResponse() on the FacesContext instance for the current request, clear the remaining events from the event queue and transfer control to the Render Response phase of the request processing lifecycle. Otherwise, control must proceed to the Update Model Values phase.

2.2.3.1. Partial Validations Partial Processing

Call FacesContext.getPartialViewContext(). Call PartialViewContext.processPartial() passing the FacesContext, PhaseID.PROCESS_VALIDATIONS as arguments.

2.2.4. Update Model Values

If this phase of the request processing lifecycle is reached, it is assumed that the incoming request is syntactically and semantically valid (according to the validations that were performed), that the local value of every component in the component tree has been updated, and that it is now appropriate to update the application’s model data in preparation for performing any application events that have been enqueued.

During the Update Model Values phase, the Jakarta Faces implementation must call the processUpdates() method of the UIViewRoot component of the tree. This will normally cause the processUpdates() method of each component in the tree to be called recursively, as described in the API reference for the UIComponent.processUpdates() method. The processUpdates() method must determine if the current request is a “partial request” by calling FacesContext.getCurrentInstance().getPartialViewContext().isPartialRequest() . If FacesContext.getCurrentInstance().getPartialViewContext().isPartialRequest() returns true, perform the sequence of steps as outlined in Update Model Values Partial Processing. The actual model update for a particular component is done in the updateModel() method for that component.

During the processing of model updates, events may have been queued by the components whose updateModel() method was invoked. As described in Common Event Processing, the processUpdates() method on the UIViewRoot component at the root of the component tree will have caused any queued events to be broadcast to interested listeners.

At the end of this phase, all appropriate model data objects will have had their values updated to match the local value of the corresponding component, and the component local values will have been cleared.

If any of the updateModel() methods that were invoked, or an event listener that processed a queued event, called responseComplete() on the FacesContext instance for the current request, clear the remaining events from the event queue and terminate lifecycle processing of the current request. If any of the updateModel() methods that was invoked, or an event listener that processed a queued event, called renderResponse() on the FacesContext instance for the current request, clear the remaining events from the event queue and transfer control to the Render Response phase of the request processing lifecycle. Otherwise, control must proceed to the Invoke Application phase.

2.2.4.1. Update Model Values Partial Processing

Call FacesContext.getPartialViewContext(). Call PartialViewContext.processPartial() passing the FacesContext, PhaseID.UPDATE_MODEL_VALUES as arguments.

2.2.5. Invoke Application

If this phase of the request processing lifecycle is reached, it is assumed that all model updates have been completed, and any remaining event broadcast to the application needs to be performed. The implementation must ensure that the processApplication() method of the UIViewRoot instance is called. The default behavior of this method will be to broadcast any queued events that specify a phase identifier of PhaseId.INVOKE_APPLICATION. If responseComplete() was called on the FacesContext instance for the current request, clear the remaining events from the event queue and terminate lifecycle processing of the current request. If renderResponse() was called on the FacesContext instance for the current request, clear the remaining events from the event queue.

Advanced applications (or application frameworks) may replace the default ActionListener instance by calling the setActionListener() method on the Application instance for this application. However, the Jakarta Faces implementation must provide a default ActionListener instance that behaves as described in ActionListener Property.

2.2.6. Render Response

This phase accomplishes two things:

  1. Causes the response to be rendered to the client

  2. Causes the state of the response to be saved for processing on subsequent requests.

Jakarta Faces supports a range of approaches that Jakarta Faces implementations may utilize in creating the response text that corresponds to the contents of the response view, including:

  • Deriving all of the response content directly from the results of the encoding methods (on either the components or the corresponding renderers) that are called.

  • Interleaving the results of component encoding with content that is dynamically generated by application programming logic.

  • Interleaving the results of component encoding with content that is copied from a static “template” resource.

  • Interleaving the results of component encoding by embedding calls to the encoding methods into a dynamic resource.

Because of the number of possible options, the mechanism for implementing the Render Response phase cannot be specified precisely. However, all Jakarta Faces implementations of this phase must conform to the following requirements:

  • If it is possible to obtain a ViewDeclarationLanguage instance for the current viewId, from the ViewHandler, its buildView() method must be called.

  • Publish the jakarta.faces.event.PreRenderViewEvent.

  • Jakarta Faces implementations must provide a default ViewHandler implementation that is capable of handling views written in the Faces View Declaration Language (VDL).

  • If all of the response content is being derived from the encoding methods of the component or associated Renderers, the component tree should be walked in the same depth-first manner as was used in earlier phases to process the component tree, but subject to the additional constraints listed here. Generally this is handled by a call to ViewHandler.renderView().

  • If the response content is being interleaved from additional sources and the encoding methods, the components may be selected for rendering in any desired order.

  • During the rendering process, additional components may be added to the component tree based on information available to the ViewHandler implementation. However, before adding a new component, the ViewHandler implementation must first check for the existence of the corresponding component in the component tree. If the component already exists (perhaps because a previous phase has pre-created one or more components), the existing component’s properties and attributes must be utilized.

  • Under no circumstances should a component be selected for rendering when its parent component, or any of its ancestors in the component tree, has its rendersChildren property set to true. In such cases, the parent or ancestor component must render the content of this child component when the parent or ancestor was selected.

  • If the isRendered() method of a component returns false, the renderer for that component must not generate any markup, and none of its facets or children (if any) should be rendered.

  • It must be possible for the application to programmatically modify the component tree at any time during the request processing lifecycle (except during the rendering of the view) and have the system behave as expected. For example, the following must be permitted. Modification of the view during rendering may lead to undefined results. It must be possible to allow components added by the templating system (such as Facelets) to be removed from the tree before rendering. It must be possible to programmatically add components to the tree and have them render in the proper place in the hierarchy. It must be possible to re-order components in the tree before rendering. These manipulations do require that any components added to the tree have ids that are unique within the scope of the closest parent NamingContainer component. The value of the rendersChildren property is handled as expected, and may be either true or false.

  • If running on a container that supports Jakarta Servlet 4.0 or later, after any dynamic component manipulations have been completed, any resources that have been added to the UIViewRoot, such as scripts, images, or stylesheets, and any inline images, must be pushed to the client using the Jakarta Servlet Server Push API. All of the pushes must be started before any of the HTML of the response is rendered to the client.

  • For partial requests, where partial view rendering is required, there must be no content written outside of the view (outside f:view). Response writing must be disabled. Response writing must be enabled again at the start of encodeBegin.

When each particular component in the component tree is selected for rendering, calls to its encodeXxx() methods must be performed in the manner described in Component Specialization Methods. For components that implement ValueHolder (such as UIInput and UIOutput), data conversion must occur as described in the UIOutput Javadocs.

Upon completion of rendering, but before state saving the Jakarta Faces runtime must publish a jakarta.faces.event.PostRenderViewEvent. After doing so the Jakarta Faces runtime must save the completed state using the methods of the class StateManager. This state information must be made accessible on a subsequent request, so that the Restore View can access it. For more on StateManager, see State Saving Methods.

2.2.6.1. Render Response Partial Processing

According to UIViewRoot.encodeChildren(), FacesContext.processPartial(PhaseId.RENDER_RESPONSE), will be called if and only if the current request is an Ajax request. Take these actions in this case.

On the ExternalContext for the request, call setResponseContentType("text/xml") and addResponseHeader("Cache-control", "no-cache"). Call startDocument() on the PartialResponseWriter.

Call writePreamble("<?xml version='1.0' encoding='currentEncoding'?>\n”) on the PartialResponseWriter, where encoding is the return from the getCharacterEncoding() on the PartialResponseWriter, or UTF-8 if that method returns null.

If isResetValues() returns true, call getRenderIds() and pass the result to UIViewRoot.resetValues().

If isRenderAll() returns true and the view root is not an instance of NamingContainer, call startUpdate(PartialResponseWriter.RENDER_ALL_MARKER) on the PartialResponseWriter. For each child of the UIViewRoot, call encodeAll(). Call endUpdate() on the PartialResponseWriter. Render the state using the algorithm described below in Partial State Rendering, call endDocument() on the PartialResponseWriter and return. If isRenderAll() returns true and this UIViewRoot is a NamingContainer, treat this as a case where isRenderAll() returned false, but use the UIViewRoot itself as the one and only component from which the tree visit must start.

If isRenderAll() returns false, if there are ids to render, visit the subset of components in the tree to be rendered in similar fashion as for other phases, but for each UIComponent in the traversal, call startUpdate(id) on the PartialResponseWriter, where id is the client id of the component. Call encodeAll() on the component, and then endUpdate() on the PartialResponseWriter. If there are no ids to render, this step is un-necessary. After the subset of components (if any) have been rendered, Render the state using the algorithm described below in Partial State Rendering, call endDocument() on the PartialResponseWriter and return.

Partial State Rendering

This section describes the requirements for rendering the <update> elements pertaining to view state and window id in the case of partial response rendering.

If the view root is marked transient, take no action and return.

Obtain a unique id for the view state, as described in the JavaDocs for the constant field ResponseStateManager.VIEW_STATE_PARAM. Pass this id to a call to startUpdate() on the PartialResponseWriter. Obtain the view state to render by calling getViewState() on the application’s StateManager. Write the state by calling write() on the PartialResponseWriter, passing the state as the argument. Call endUpdate() on the PartialResponseWriter.

If getClientWindow() on the ExternalContext, returns non-null, obtain an id for the <update> element for the window id as described in the JavaDocs for the constant ResponseStateManager.WINDOW_ID_PARAM. Pass this id to a call to startUpdate() on the PartialResponseWriter. Call write() on that same writer, passing the result of calling getId() on the ClientWindow. Call endUpdate() on the PartialResponseWriter.

2.3. Common Event Processing

For a complete description of the event processing model for Jakarta Faces components, see Event and Listener Model.

During several phases of the request processing lifecycle, as described in Standard Request Processing Lifecycle Phases, the possibility exists for events to be queued (via a call to the queueEvent() method on the source UIComponent instance, or a call to the queue() method on the FacesEvent instance), which must now be broadcast to interested event listeners. The broadcast is performed as a side effect of calling the appropriate lifecycle management method (processDecodes(), processValidators(), processUpdates(), or processApplication()) on the UIViewRoot instance at the root of the current component tree.

For each queued event, the broadcast() method of the source UIComponent must be called to broadcast the event to all event listeners who have registered an interest, on this source component for events of the specified type, after which the event is removed from the event queue. See the API reference for the UIComponent.broadcast() method for the detailed functional requirements.

It is also possible for event listeners to cause additional events to be enqueued for processing during the current phase of the request processing lifecycle. Such events must be broadcast in the order they were enqueued, after all originally queued events have been broadcast, before the lifecycle management method returns.

2.4. Common Application Activities

The following subsections describe common activities that may be undertaken by an application that is using Jakarta Faces to process an incoming request and/or create an outgoing response. Their use is described in Request Processing Lifecycle Scenarios, for each request processing lifecycle scenario in which the activity is relevant.

2.4.1. Acquire Faces Object References

This phase is only required when the request being processed was not submitted from a previous response, and therefore did not initiate the Faces Request Generates Faces Response lifecycle. In order to generate a Faces Response, the application must first acquire references to several objects provided by the Jakarta Faces implementation, as described below.

2.4.1.1. Acquire and Configure Lifecycle Reference

As described in Lifecycle, the Jakarta Faces implementation must provide an instance of jakarta.faces.lifecycle.Lifecycle that may be utilized to manage the remainder of the request processing lifecycle. An application may acquire a reference to this instance in a portable manner, as follows:

LifecycleFactory lFactory = (LifecycleFactory)
    FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
Lifescycle lifecycle =
    lFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);

It is also legal to specify a different lifecycle identifier as a parameter to the getLifecycle() method, as long as this identifier is recognized and supported by the Jakarta Faces implementation you are using. However, using a non-default lifecycle identifier will generally not be portable to any other Jakarta Faces implementation.

2.4.1.2. Acquire and Configure FacesContext Reference

As described in FacesContext, the Jakarta Faces implementation must provide an instance of jakarta.faces.context.FacesContext to contain all of the per-request state information for a Faces Request or a Faces Response. An application that is processing a Non-Faces Request, but wants to create a Faces Response, must acquire a reference to a FacesContext instance as follows

FacesContextFactory fcFactory = (FacesContextFactory)
    FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
FacesContext facesContext =
    fcFactory.getFacesContext(context, request, response, lifecycle);

where the context, request, and response objects represent the corresponding instances for the application environment. For example, in a Jakarta Servlet-based application, these would be the ServletContext, HttpServletRequest, and HttpServletResponse instances for the current request.

2.4.2. Create And Configure A New View

When a Faces response is being intially created, or when the application decides it wants to create and configure a new view that will ultimately be rendered, it may follow the steps described below in order to set up the view that will be used. You must start with a reference to a FacesContext instance for the current request.

2.4.2.1. Create A New View

Views are represented by a data structure rooted in an instance of jakarta.faces.component.UIViewRoot, and identified by a view identifier whose meaning depends on the ViewHandler implementation to be used during the Render Response phase of the request processing lifecycle. The ViewHandler provides a factory method that may be utilized to construct new component trees, as follows:

String viewId = ... identifier of the desired Tree ...;
ViewHandler viewHandler = application.getViewHandler();
UIViewRoot view = viewHandler.createView(facesContext, viewId);

The UIViewRoot instance returned by the createView() method must minimally contain a single UIViewRoot provided by the Jakarta Faces implementation, which must encapsulate any implementation-specific component management that is required. Optionally, a Jakarta Faces implementation’s ViewHandler may support the automatic population of the returned UIViewRoot with additional components, perhaps based on some external metadata description.

The caller of ViewHandler.createView() must cause the FacesContext to be populated with the new UIViewRoot. Applications must make sure that it is safe to discard any state saved in the view rooted at the UIViewRoot currently stored in the FacesContext. If Facelets is the page definition language, FacesContext.setViewRoot() must be called before returning from ViewHandler.createView(). Refer to Default ViewHandler Implementation for more ViewHandler details.

2.4.2.2. Configure the Desired RenderKit

The UIViewRoot instance provided by the ViewHandler, as described in the previous subsection, must automatically be configured to utilize the default jakarta.faces.render.RenderKit implementation provided by the Jakarta Faces implementation, as described in RenderKit. This RenderKit must support the standard components and Renderers described later in this specification, to maximize the portability of your application.

However, a different RenderKit instance provided by your Jakarta Faces implementation (or as an add-on library) may be utilized instead, if desired. A reference to this RenderKit instance can be obtained from the standard RenderKitFactory, and then assigned to the UIViewRoot instance created previously, as follows:

String renderKitId = ... identifier of desired RenderKit ...;
RenderKitFactory rkFactory = (RenderKitFactory)
    FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
RenderKit renderKit = rkFactory.getRenderKit(renderKitId, facesContext);
view.setRenderKitId(renderKitId);

As described in Chapter 8, changing the RenderKit being used changes the set of Renderers that will actually perform decoding and encoding activities. Because the components themselves store only a rendererType property (a logical identifier of a particular Renderer), it is thus very easy to switch between RenderKits, as long as they support renderers with the same renderer types.

The default ViewHandler must call calculateRenderKitId() on itself and set the result into the UIViewRoot’s renderKitId property. This allows applications that use alternative RenderKits to dynamically switch on a per-view basis.

2.4.2.3. Configure The View’s Components

At any time, the application can add new components to the view, remove them, or modify the attributes and properties of existing components. For example, a new FooComponent (an implementation of UIComponent) can be added as a child to the root UIViewRoot in the component tree as follows:

FooComponent component = ... create a FooComponent instance ...;
facesContext.getViewRoot().getChildren().add(component);
2.4.2.4. Store the new View in the FacesContext

Once the view has been created and configured, the FacesContext instance for this request must be made aware of it by calling setViewRoot().

2.5. Concepts that impact several lifecycle phases

This section is intended to give the reader a “big picture” perspective on several complex concepts that impact several request processing lifecycle phases.

2.5.1. Value Handling

At a fundamental level, Jakarta Faces is a way to get values from the user, into your model tier for processing. The process by which values flow from the user to the model has been documented elsewhere in this spec, but a brief holistic survey comes in handy. The following description assumes the Jakarta Servlet/HTTP case, and that all components have Renderers.

2.5.1.1. Apply Request Values Phase

The user presses a button that causes a form submit to occur. This causes the state of the form to be sent as name=value pairs in the POST data of the HTTP request. The Jakarta Faces request processing lifecycle is entered, and eventually we come to the Apply Request Values Phase. In this phase, the decode() method for each Renderer for each UIComponent in the view is called. The Renderer takes the value from the request and passes it to the setSubmittedValue() method of the component, which is, of course, an instance of EditableValueHolder. If the component has the “immediate” property set to true, we execute validation immediately after decoding. See below for what happens when we execute validation.

2.5.1.2. Process Validators Phase

processValidators() is called on the root of the view. For each EditableValueHolder in the view, If the “immediate” property is not set, we execute validation for each UIInput in the view. Otherwise, validation has already occurred and this phase is a no-op.

2.5.1.3. Executing Validation

Please see the javadocs for UIInput.validate() for more details, but basically, this method gets the submitted value from the component (set during Apply Request Values), gets the Renderer for the component and calls its getConvertedValue(), passing the submitted value. If a conversion error occurs, it is dealt with as described in the javadocs for that method. Otherwise, all validators attached to the component are asked to validate the converted value. If any validation errors occur, they are dealt with as described in the javadocs for Validator.validate(). The converted value is pushed into the component’s setValue() method, and a ValueChangeEvent is fired if the value has changed.

2.5.1.4. Update Model Values Phase

For each UIInput component in the view, its updateModel() method is called. This method only takes action if a local value was set when validation executed and if the page author configured this component to push its value to the model tier. This phase simply causes the converted local value of the UIInput component to be pushed to the model in the way specified by the page author. Any errors that occur as a result of the attempt to push the value to the model tier are dealt with as described in the javadocs for UIInput.updateModel().

2.5.2. Localization and Internationalization (L10N/I18N)

Jakarta Faces is fully internationalized. The I18N capability in Jakarta Faces builds on the I18N concepts offered in the Jakarta Servlet and Jakarta Tags specifications. I18N happens at several points in the request processing lifecycle, but it is easiest to explain what goes on by breaking the task down by function.

2.5.2.1. Determining the active Locale

Jakarta Faces has the concept of an active Locale which is used to look up all localized resources. Converters must use this Locale when performing their conversion. This Locale is stored as the value of the locale JavaBeans property on the UIViewRoot of the current FacesContext. The application developer can tell Jakarta Faces what locales the application supports in the applications’ WEB-INF/faces-config.xml file. For example:

<faces-config>
  <application>
    <locale-config>
      <default-locale>en</default-locale>
      <supported-locale>de</supported-locale>
      <supported-locale>fr</supported-locale>
      <supported-locale>es</supported-locale>
    </locale-config>
  </application>

This application’s default locale is en, but it also supports de, fr, and es locales. These elements cause the Application instance to be populated with Locale data. Please see the javadocs for details.

The UIViewRoot’s Locale is determined and set by the ViewHandler during the execution of the ViewHandler ’s createView() method. This method must cause the active Locale to be determined by looking at the user’s preferences combined with the application’s stated supported locales. Please see the javadocs for details.

The application can call UIViewRoot.setLocale() directly, but it is also possible for the page author to override the UIViewRoot’s locale by using the locale attribute on the <f:view> tag. The value of this attribute must be specified as language[{-|_}country[{-|_}variant]] without the colons, for example "ja_JP_SJIS". The separators between the segments must be ’ - ’ or ’ _ ’.

To facilitate BCP 47 support, the Locale parsing mentioned above is done only if the JDK Locale.languageForTag method does not return a Locale with a language in it. The additional format of the Locale string is as specified by that method.

2.5.2.2. Determining the Character Encoding

The request and response character encoding are set and interpreted as follows.

On an initial request to a Faces webapp, the request character encoding is left unmodified, relying on the underlying request object (e.g., the Jakarta Servlet or Portlet request) to parse request parameter correctly.

At the beginning of the render-response phase, the ViewHandler must ensure that the response Locale is set to be that of the UIViewRoot, for example by calling ServletResponse.setLocale() when running in the Jakarta Servlet environment. Setting the response Locale may affect the response character encoding, see the Jakarta Servlet and Portlet specifications for details.

At the end of the render-response phase, the ViewHandler must store the response character encoding used by the underlying response object (e.g., the Jakarta Servlet or Portlet response) in the session (if and only if a session already exists) under a well known, implementation-dependent key.

On a subsequent postback, before any of the ExternalContext methods for accessing request parameters are invoked, the ViewHandler must examine the Content-Type header to read the charset attribute and use its value to set it as the request encoding for the underlying request object. If the Content-Type header doesn’t contain a charset attribute, the encoding previously stored in the session (if and only if a session already exists), must be used to set the encoding for the underlying request object. If no character encoding is found, the request encoding must be left unmodified.

The above algorithm allows an application to use the mechanisms of the underlying technologies to adjust both the request and response encoding in an application-specific manner. Note, though, that the character encoding rules prior to Jakarta Servlet 2.4 are imprecise and special care must be taken for portability between containers.

2.5.2.3. Localized Text

Since most Jakarta Faces components allow pulling their display value from the model tier, it is easy to do the localization at the model tier level. As a convenience, Jakarta Faces provides the <f:loadBundle> tag, which takes a ResourceBundle and loads it into a Map, which is then stored in the scoped namespace in request scope, thus making its messages available using the same mechanism for accessing data in the model tier. For example:

<f:loadBundle basename="com.foo.industryMessages.chemical"
              var="messages" />
<h:outputText value="#{messages.benzene}" />

This must cause the ResourceBundle named com.foo.industryMessages.chemical to be loaded as a Map into the request scope under the key messages. Localized content can then be pulled out of it using the normal value expression syntax.

2.5.2.4. Localized Application Messages

This section describes how Jakarta Faces handles localized error and informational messages that occur as a result of conversion, validation, or other application actions during the request processing lifecycle. The Jakarta Faces class jakarta.faces.application.FacesMessage is provided to encapsulate summary, detail, and severity information for a message. A Jakarta Faces implementation must provide a jakarta.faces.Messages ResourceBundle containing all of the necessary keys for the standard messages. The required keys (and a non-normative indication of the intended message text) are as follows:

  • jakarta.faces.component.UIInput.CONVERSION={0}: Conversion error occurred

  • jakarta.faces.component.UIInput.REQUIRED={0}: Validation Error: Value is required

  • jakarta.faces.component.UIInput.UPDATE= {0}: An error occurred when processing your submitted information

  • jakarta.faces.component.UISelectOne.INVALID={0}: Validation Error: Value is not valid

  • jakarta.faces.component.UISelectMany.INVALID={0}: Validation Error: Value is not valid

  • jakarta.faces.converter.BigDecimalConverter.DECIMAL={2}: ''{0}'' must be a signed decimal number.

  • jakarta.faces.converter.BigDecimalConverter.DECIMAL_detail={2}: ''{0}'' must be a signed decimal number consisting of zero or more digits, that may be followed by a decimal point and fraction. Example: {1}

  • jakarta.faces.converter.BigIntegerConverter.BIGINTEGER={2}: ''{0}'' must be a number consisting of one or more digits.

  • jakarta.faces.converter.BigIntegerConverter.BIGINTEGER_detail={2}: ''{0}'' must be a number consisting of one or more digits. Example: {1}

  • jakarta.faces.converter.BooleanConverter.BOOLEAN={1}: ''{0}'' must be 'true' or 'false'.

  • jakarta.faces.converter.BooleanConverter.BOOLEAN_detail={1}: ''{0}'' must be 'true' or 'false'. Any value other than 'true' will evaluate to 'false'.

  • jakarta.faces.converter.ByteConverter.BYTE={2}: ''{0}'' must be a number between -128 and 127.

  • jakarta.faces.converter.ByteConverter.BYTE_detail={2}: ''{0}'' must be a number between -128 and 127. Example: {1}

  • jakarta.faces.converter.CharacterConverter.CHARACTER={1}: ''{0}'' must be a valid character.

  • jakarta.faces.converter.CharacterConverter.CHARACTER_detail={1}: ''{0}'' must be a valid ASCII character.

  • jakarta.faces.converter.DateTimeConverter.DATE={2}: ''{0}'' could not be understood as a date.

  • jakarta.faces.converter.DateTimeConverter.DATE_detail={2}: ''{0}'' could not be understood as a date. Example: {1}

  • jakarta.faces.converter.DateTimeConverter.TIME={2}: ''{0}'' could not be understood as a time.

  • jakarta.faces.converter.DateTimeConverter.TIME_detail={2}: ''{0}'' could not be understood as a time. Example: {1}

  • jakarta.faces.converter.DateTimeConverter.DATETIME={2}: ''{0}'' could not be understood as a date and time.

  • jakarta.faces.converter.DateTimeConverter.DATETIME_detail={2}: '{0}'' could not be understood as a date and time. Example: {1}

  • jakarta.faces.converter.DateTimeConverter.PATTERN_TYPE={1}: A 'pattern' or 'type' attribute must be specified to convert the value ''{0}''.

  • jakarta.faces.converter.DoubleConverter.DOUBLE={2}: ''{0}'' must be a number consisting of one or more digits.

  • jakarta.faces.converter.DoubleConverter.DOUBLE_detail={2}: ''{0}'' must be a number between 4.9E-324 and 1.7976931348623157E308 Example: {1}

  • jakarta.faces.converter.EnumConverter.ENUM={2}: ''{0}'' must be convertible to an enum.

  • jakarta.faces.converter.EnumConverter.ENUM_detail={2}: ''{0}'' must be convertible to an enum from the enum that contains the constant ''{1}''.

  • jakarta.faces.converter.EnumConverter.ENUM_NO_CLASS={1}: ''{0}'' must be convertible to an enum from the enum, but no enum class provided.

  • jakarta.faces.converter.EnumConverter.ENUM_NO_CLASS_detail={1}: ''{0}'' must be convertible to an enum from the enum, but no enum class provided.

  • jakarta.faces.converter.FloatConverter.FLOAT={2}: ''{0}'' must be a number consisting of one or more digits.

  • jakarta.faces.converter.FloatConverter.FLOAT_detail={2}: ''{0}'' must be a number between 1.4E-45 and 3.4028235E38 Example: {1}

  • jakarta.faces.converter.IntegerConverter.INTEGER={2}: ''{0}'' must be a number consisting of one or more digits.

  • jakarta.faces.converter.IntegerConverter.INTEGER_detail={2}: ''{0}'' must be a number between -2147483648 and 2147483647 Example: {1}

  • jakarta.faces.converter.LongConverter.LONG={2}: ''{0}'' must be a number consisting of one or more digits.

  • jakarta.faces.converter.LongConverter.LONG_detail={2}: ''{0}'' must be a number between -9223372036854775808 to 9223372036854775807 Example: {1}

  • jakarta.faces.converter.NumberConverter.CURRENCY={2}: ''{0}'' could not be understood as a currency value.

  • jakarta.faces.converter.NumberConverter.CURRENCY_detail={2}: ''{0}'' could not be understood as a currency value. Example: {1}

  • jakarta.faces.converter.NumberConverter.PERCENT={2}: ''{0}'' could not be understood as a percentage.

  • jakarta.faces.converter.NumberConverter.PERCENT_detail={2}: ''{0}'' could not be understood as a percentage. Example: {1}

  • jakarta.faces.converter.NumberConverter.NUMBER={2}: ''{0}'' is not a number.

  • jakarta.faces.converter.NumberConverter.NUMBER_detail={2}: ''{0}'' is not a number. Example: {1}

  • jakarta.faces.converter.NumberConverter.PATTERN={2}: ''{0}'' is not a number pattern.

  • jakarta.faces.converter.NumberConverter.PATTERN_detail={2}: ''{0}'' is not a number pattern. Example: {1}

  • jakarta.faces.converter.ShortConverter.SHORT={2}: ''{0}'' must be a number consisting of one or more digits.

  • jakarta.faces.converter.ShortConverter.SHORT_detail={2}: ''{0}'' must be a number between -32768 and 32767 Example: {1}

  • jakarta.faces.converter.STRING={1}: Could not convert ''{0}'' to a string.

  • jakarta.faces.validator.BeanValidator.MESSAGE={0}

  • jakarta.faces.validator.DoubleRangeValidator.MAXIMUM={1}: Validation Error: Value is greater than allowable maximum of ''{0}''

  • jakarta.faces.validator.DoubleRangeValidator.MINIMUM={1}: Validation Error: Value is less than allowable minimum of ''{0}''

  • jakarta.faces.validator.DoubleRangeValidator.NOT_IN_RANGE={2}: Validation Error: Specified attribute is not between the expected values of {0} and {1}.

  • jakarta.faces.validator.DoubleRangeValidator.TYPE={0}: Validation Error: Value is not of the correct type

  • jakarta.faces.validator.LengthValidator.MAXIMUM={1}: Validation Error: Length is greater than allowable maximum of ''{0}''

  • jakarta.faces.validator.LengthValidator.MINIMUM={1}: Validation Error: Length is less than allowable minimum of ''{0}''

  • jakarta.faces.validator.LongRangeValidator.MAXIMUM={1}: Validation Error: Value is greater than allowable maximum of ''{0}''

  • jakarta.faces.validator.LongRangeValidator.MINIMUM={1}: Validation Error Value is less than allowable minimum of ''{0}''

  • jakarta.faces.validator.LongRangeValidator.NOT_IN_RANGE={2}: Validation Error: Specified attribute is not between the expected values of {0} and {1}.

  • jakarta.faces.validator.LongRangeValidator.TYPE={0}: Validation Error: Value is not of the correct type

A Jakarta Faces application may provide its own messages, or overrides to the standard messages by supplying a <message-bundle> element to in the application configuration resources. Since the ResourceBundle provided in the Java platform has no notion of summary or detail, Jakarta Faces adopts the policy that ResourceBundle key for the message looks up the message summary. The detail is stored under the same key as the summary, with detail appended. These ResourceBundle keys must be used to look up the necessary values to create a localized FacesMessage instance. Note that the value of the summary and detail keys in the ResourceBundle may contain parameter substitution tokens, which must be substituted with the appropriate values using java.text.MessageFormat. Replace the last parameter substitution token shown in the messages above with the input component’s label attribute. For example, {1} for “DoubleRangeValidator.MAXIMUM”, {2} for “ShortConverter.SHORT”. The label attribute is a generic attribute. Please see Generic Attributes and Standard HTML RenderKit Implementation for more information on these attributes. If the input component’s label attribute is not specified, use the component’s client identifier.

These messages can be displayed in the page using the UIMessage and UIMessages components and their corresponding tags, <h:message> and <h:messages>.

The following algorithm must be used to create a FacesMessage instance given a message key.

  • Call getMessageBundle() on the Application instance for this web application, to determine if the application has defined a resource bundle name. If so, load that ResourceBundle and look for the message there.

  • If not there, look in the jakarta.faces.Messages resource bundle.

  • In either case, if a message is found, use the above conventions to create a FacesMessage instance.

2.5.3. State Management

Jakarta Faces introduces a powerful and flexible system for saving and restoring the state of the view between requests to the server. It is useful to describe state management from several viewpoints. For the page author, state management happens transparently. For the app assembler, state management can be configured to save the state in the client or on the server by setting the ServletContext InitParameter named jakarta.faces.STATE_SAVING_METHOD to either client or server. The value of this parameter directs the state management decisions made by the implementation.

2.5.3.1. State Management Considerations for the Custom Component Author

Since the component developer cannot know what the state saving method will be at runtime, they must be aware of state management. As shown in The jakarta.faces.component package, all Jakarta Faces components implement the StateHolder interface. As a consequence the standard components provide implementations of PartialStateHolder to suit their needs. A custom component that extends UIComponent directly, and does not extend any of the standard components, must implement PartialStateHolder (or its older super-interface, StateHolder), manually. The helper class StateHelper exists to simplify this process for the custom component author. Please see PartialStateHolder or StateHolder for details.

A custom component that does extend from one of the standard components and maintains its own state, in addition to the state maintained by the superclass must take special care to implement StateHolder or PartialStateHolder correctly. Notably, calls to saveState() must not alter the state in any way. The subclass is responsible for saving and restoring the state of the superclass. Consider this example. My custom component represents a “slider” ui widget. As such, it needs to keep track of the maximum value, minimum value, and current values as part of its state.

public class Slider extends UISelectOne {
  protected Integer min = null;
  protected Integer max = null;
  protected Integer cur = null;

  // ... details omitted
  public Object saveState(FacesContext context) {
    Object values[] = new Object[4];
    values[0] = super.saveState(context);
    values[1] = min;
    values[2] = max;
    values[3] = cur;
  }

  public void restoreState(FacesContext context, Object state) {
    Object values[] = (Object {}) state; // guaranteed to succeed
    super.restoreState(context, values[0]);
    min = (Integer) values[1];
    max = (Integer) values[2];
    cur = (Integer) values[3];
  }

Note that we call super.saveState() and super.restoreState() as appropriate. This is absolutely vital! Failing to do this will prevent the component from working.

2.5.3.2. State Management Considerations for the Jakarta Faces Implementor

The intent of the state management facility is to make life easier for the page author, app assembler, and component author. However, the complexity has to live somewhere, and the Jakarta Faces implementor is the lucky role. Here is an overview of the key players. Please see the javadocs for each individual class for more information.

Key Players in State Management
  • StateHelper the helper class that defines a Map -like contract that makes it easier for components to implement PartialStateHolder.

  • ViewHandler the entry point to the state management system. Uses a helper class, StateManager, to do the actual work.

  • StateManager abstraction for the hard work of state saving. Uses a helper class, ResponseStateManager, for the rendering technology specific decisions.

  • ResponseStateManager abstraction for rendering technology specific state management decisions.

  • UIComponent directs process of saving and restoring individual component state.

2.5.4. Resource Handling

This section only applies to pages written using Facelets. Resource Handling is the starting point for the normative specification for Resource Handling. This section gives a non-normative overview of the feature. The following steps walk through the points in the lifecycle where this feature is encountered. Consider a Faces web application that contains resources that have been packaged into the application as specified in Packaging Resources. Assume each page in the application includes references to resources, specifically scripts and stylesheets. The first diagram in this chapter is helpful in understanding this example.

Consider an initial request to the application.

  • The ViewHandler calls ViewDeclarationLanguage.buildView(). This ultimately causes the processEvent() method for the jakarta.faces.resource.Script and jakarta.faces.resource.Stylesheet renderers (which implement ComponentSystemEventListener) to be called after each component that declares them as their renderer is added to the view. This method is specified to take actions that cause the resource to be rendered at the correct part in the page based on user-specified or application invariant rules. Here’s how it works.

  • Every UIComponent instance in a view is created with a call to some variant of Application.createComponent(). The specification for this method now includes some annotation processing requirements. If the component or its renderer has an @ListenerFor or @ListenersFor annotation, and the Script and Stylesheet renderers must, the component or its renderer are added as a component scoped listener for the appropriate event. In the case of Script and Stylesheet renderers, they must listen for the PostAddToViewEvent.

  • When the processEvent() method is called on a Script or Stylesheet renderer, the renderer takes the specified action to move the component to the proper point in the tree based on what kind of resource it is, and on what hints the page author has declared on the component in the view.

  • The ViewHandler calls ViewDeclarationLanguage.renderView(). The view is traversed as normal and because the components with Script and Stylesheet renderers have already been reparented to the proper place in the view, the normal renderering causes the resource to be encoded as described in Rendering Resources.

The browser then parses the completely rendered page and proceeds to issue subsequent requests for the resources included in the page.

Now consider a request from the browser for one of those resources included in the page.

  • The request comes back to the Faces server. The FacesServlet is specified to call ResourceHandler.isResourceRequest() as shown in the diagram in Faces Request Generates Faces Response. In this case, the method returns true. The FacesServlet is specified to call ResourceHandler.handleResourceRequest() to serve up the bytes of the resource.

2.5.5. View Parameters

This section only applies to pages written using Facelets. The normative specification for this feature is spread out across several places, including the View Declaration Language Documentation for the <f:metadata> element, the javadocs for the UIViewParameter, ViewHandler, and ViewDeclarationLanguage classes, and the spec language requirements for the default NavigationHandler and the Request Processing Lifecycle. This leads to a very diffuse field of specification requirements. To aid in understanding the feature, this section provides a non-normative overview of the feature. The following steps walk through the points in the lifecycle where this feature is encountered. Consider a web application that uses this feature exclusively on every page. Therefore every page has the following features in common.

  • Every page has an <f:metadata> tag, with at least one <f:viewParameter> element within it.

  • Every page has at least one <h:link> or < h:button> with the appropriate parameters nested within it.

  • No other kind of navigation components are used in the application.

Consider an initial request to the application.

  • As specified in section Restore View, the restore view phase of the request processing lifecycle detects that this is an initial request and tries to obtain the ViewDeclarationLanguage instance from the ViewHandler for this viewId. Because every page in the app is written in Facelets, there is a ViewDeclarationLanguage instance. Restore view phase calls ViewDeclarationLanguage.getViewMetadata(). Because every view in this particular app does have <f:metadata> on every page, this method returns a ViewMetadata instance. Restore view phase calls MetaData.createMetadataView(). This method creates a UIViewRoot containing only children declared in the <f:metadata> element. Restore view phase calls ViewMetadata.getViewParameters(). Because every <f:metadata> in the app has at least one <f:viewParameter> element within it, this method returns a non empty Collection<UIViewParameter>. Restore view phase uses this fact to decide that the lifecycle must not skip straight to render response, as is the normal action taken on initial requests.

  • The remaining phases of the request processing lifecycle execute: apply request values, process validations, update model values, invoke application, and finally render response. Because the view only contains UIViewParameter children, only these children are traversed during the lifecycle, but because this is an initial request, with no query parameters, none of these compnents take any action during the lifecycle.

  • Because the pages exclusively use <h:link> and <h:button> for their navigation, the renderers for these components are called during the rendering of the page. As specified in the renderkit docs for the renderers for those components, markup is rendered that causes the browser to issue a GET request with query parameters.

Consider when the user clicks on a link in the application. The browser issues a GET request with query parameters

  • Restore view phase takes the same action as in the previously explained request. Because this is a GET request, no state is restored from the previous request.

  • Because this is a request with query parameters, the UIViewParameter children do take action when they are traversed during the normal lifecycle, reading values during the apply request values phase, doing conversion and processing validators attached to the <f:viewParam> elements, if any, and updating models during the update model values phase. Because there are only <h:link> and <h:button> navigation elements in the page, no action action will happen during the invoke application phase. The response is re-rendered as normal. In such an application, the only navigation to a new page happens by virtue of the browser issuing a GET request to a different viewId.

2.5.6. Bookmarkability

Jakarta Faces has a bookmarking capability with the use of two Standard HTML RenderKit additions.

Provided is a component (UIOutcomeTarget) that provides properties that are used to produce a hyperlink at render time. The component can appear in the form of a button or a link. This feature introduces a concept known as “preemptive navigation”, which means the target URL is determined at Render Response time - before the user has activated the component. This feature allows the user to leverage the navigation model while also providing the ability to generate bookmarkable non-faces requests.

2.5.7. Jakarta Bean Validation

Jakarta Faces supports Jakarta Bean Validation. A Jakarta Faces implementation must support Jakarta Bean Validation if the environment in which the Jakarta Faces runtime is included requires Jakarta Bean Validation. Currently the only such environment is when Jakarta Faces is included in a Jakarta EE runtime.

A detailed description of the usage of Jakarta Bean Validation with Jakarta Faces is beyond the scope of this section, but this section will provide a brief overview of the feature, touching on the points of interest to a spec implementor. Consider a simple web application that has one page, written in Facelets, that has several text fields inside of a form. This application is running in a Jakarta Faces runtime in an environment that does require Jakarta Bean Validation, and therefore this feature is available. Assume that every text field is bound to a managed bean property that has at least one Jakarta Bean Validation constraint annotation attached to it.

During the render response phase that always precedes a postback, due to the specification requirements in Validation Registration, every UIInput in this application has an instance of Validator with id jakarta.faces.Bean attached to it.

During the process validations phase, due to the specification for the validate() method of this Validator, Bean Validation is invoked automatically, for the user specified validation constraints, whenever such components are normally validated. The jakarta.faces.Bean standard validator also ensures that every ConstraintViolation that resulted in attempting to validate the model data is wrapped in a FacesMessage and added to the FacesContext as normal with every other kind of validator.

2.5.8. Ajax

Jakarta Faces supports Ajax. The specification contains a JavaScript library for performing basic Ajax operations. The library helps define a standard way of sending an Ajax request, and processing an Ajax response, since these are problem areas for component compatibility. The specification provides two ways of adding Ajax to Jakarta Faces web applications. Page authors may use the JavaScript library directly in their pages by attaching the Ajax request call to a Jakarta Faces component via a JavaScript event (such as onclick). They may also take a more declarative approach and use a core Facelets tag (<f:ajax/>) that they can nest within Jakarta Faces components to “Ajaxify” them. It is also possible to “Ajaxify” regions of a page by “wrapping” the tag around component groups.

The server side aspects of Jakarta Faces Ajax frameworks work with the standard Jakarta Faces lifecycle. In addition to providing a standard page authoring experience, the specification also standardizes the server side processing of Ajax requests. Selected components in a Jakarta Faces view can be processed (known as partial processing) and selected components can be rendered to the client (known as partial rendering).

2.5.9. Component Behaviors

The Jakarta Faces specification contains a type of attached object known as component behaviors. Component behaviors play a similar role to converters and validators in that they are attached to a component instance in order to enhance the component with additional functionality not defined by the component itself. While converters and validators are currently limited to the server-side request processing lifecycle, component behaviors have impact that extends to the client, within the scope of a particular instance component in a view. In particular, the ClientBehavior interface defines a contract for behaviors that can enhance a component’s rendered content with behavior-defined "scripts". These scripts are executed on the client in response to end user interaction, but can also trigger postbacks back into the Jakarta Faces request processing lifecycle.

The usage pattern for client behaviors is as follows:

  • The page author attaches a client behavior to a component, typically by specifying a behavior tag as a child of a component tag.

  • When attaching a client behavior to a component, the page author identifies the name of a client "event" to attach to. The set of valid events are defined by the component.

  • At render time, the component (or renderer) retrieves the client behavior and asks it for its script.

  • The component (or renderer) renders this script at the appropriate location in its generated content (eg. typically in a DOM event handler).

  • When the end user interacts with the component’s content in the browser, the behavior-defined script is executed in response to the page author-specified event.

  • The script provides some client-side interaction, for example, hiding or showing content or validating input on the client, and possibly posts back to the server.

The first client behavior provided by the Jakarta Faces specification is the AjaxBehavior. This behavior is exposed to a page author as a Facelets <f:ajax> tag, which can be embedded within any of the standard HTML components as follows:

<h:commandButton>
  <f:ajax event="mouseover" />
</h:commandButton>

When activated in response to end user activity, the <f:ajax> client behavior generates an Ajax request back into the Jakarta Faces request processing lifecycle.

The component behavior framework is extensible and allows developers to define custom behaviors and also allows component authors to enhance custom components to work with behaviors.

2.5.10. System Events

System Events are normatively specified in System Events. This section provides an overview of this feature as it relates to the lifecycle.

System events expand on the idea of lifecycle PhaseEvents. With PhaseEvents, it is possible to have application scoped PhaseListeners that are given the opportunity to act on the system before and after each phase in the lifecycle. System events provide a much more fine grained insight into the system, allowing application or component scoped listeners to be notified of a variety of kinds of events. The set of events supported in the core specification is given in Event Classes. To accomodate extensibility, users may define their own kinds of events.

The system event feature is a simple publish/subscribe event model. There is no event queue, events are published immediately, and always with a call to Application.publishEvent(). There are several ways to declare interest in a particular kind of event.

  • Call Application.subscribeToEvent() to add an application scoped listener.

  • Call UIComponent.subscribeToEvent() to add a component scoped listener.

  • Use the <f:event> tag to declare a component scoped listener.

  • Use the @ListenerFor or @ListenersFor annotation. The scope of the listener is determined by the code that processes the annotation.

  • Use the <system-event-listener> element in an application configuration resource to add an application scoped listener.

This feature is conceptually related to the lifecycle because there are calls to Application.publishEvent() sprinkled throughout the code that gets executed when the lifecycle runs.

2.6. Resource Handling

As shown in the diagram in Faces Request Generates Faces Response, the Jakarta Faces run-time must determine if the current Faces Request is a Faces Resource Request or a View Request. This must be accomplished by calling Application.getResourceHandler().isResourceRequest(). Most of the normative specification for resource handling is contained in the Javadocs for ResourceHandler and its related classes. This section contains the specification for resource handling that fits best in prose, rather than in Javadocs.

2.6.1. Packaging Resources

ResourceHandler defines a path based packaging convention for resources. The default implementation of ResourceHandler must support packaging resources in the web application root or in the classpath, according to the following specification.Other implementations of ResourceHandler are free to package resources however they like.

2.6.1.1. Packaging Resources into the Web Application Root

The default implementation must support packaging resources in the web application root under the path

resources/<resourceIdentifier>

relative to the web app root. Resources packaged into the web app root must be accessed using the getResource*() methods on ExternalContext.

2.6.1.2. Packaging Resources into the Classpath

For the default implementation, resources packaged in the classpath must reside under the JAR entry name:

META-INF/resources/<resourceIdentifier>

Resources packaged into the classpath must be accessed using the getResource*() methods of the ClassLoader obtained by calling the getContextClassLoader() method of the curreth Thread.

2.6.1.3. Resource Identifiers

<resourceIdentifier> consists of several segments, specified as follows.

[localePrefix/][libraryName/][libraryVersion/]resourceName[/resourceVersion]

The run-time must enforce the following rules to consider a <resourceIdentifier> valid. A <resourceIdentifier> that does not follow these rules must not be considered valid and must be ignored silently.

  • The set of characters that are valid for use in the localePrefix, libraryName, libraryVerison, resourceName and resourceVersion segments of the resource identifier is specififed as XML NameChar excluding the path separator and ‘:’ characters. The specification for XML NameChar may be seen at https://www.w3.org/TR/REC-xml/#NT-NameChar.

  • A further restriction applies to libraryName. A libraryName must not be an underscore separated sequence of non-negative integers or a locale string. More rigorously, a libraryName must not match either of the following regular expressions:

    [0-9]+(_[0-9]+)*
    [A-Za-z]{2}(_[A-Za-z]{2}(_[A-Za-z]+)*)?
  • Segments in square brackets [] are optional.

  • The segments must appear in the order shown above.

  • If libraryVersion is present, it must be preceded by libraryName.

  • If libraryVersion is present, any leaf files under libraryName must be ignored.

  • If resourceVersion is present, it must be preceded by resourceName.

  • There must be a ’ / ’ between adjacent segments in a <resourceIdentifier>

  • If libraryVersion or resourceVersion are present, both must be a ’ _ ’ separated list of integers, neither starting nor ending with ’ _ ’

If resourceVersion is present, it must be a version number in the same format as libraryVersion. An optional “file extension” may be used with the resourceVersion. If “file extension” is used, a “.” character, followed by a “file extension” must be appended to the version number. See the following table for an example.

The following examples illustrate the nine valid combinations of the above resource identifier segments.

localePrefx

libraryName

library

Version [optional]

resourceName

resource

Version [optional]

Description

actual resourceIdentifier

__

__  

__

duke.gif

__

A non-localized, non-versioned image resource called "duke.gif", not in a library

duke.gif

__

corporate

__

duke.gif

__

A non-localized, non-versioned image resource called "duke.gif" in a library called "corporate"

corporate/duke.gif

__

corporate

2_3

duke.gif

__

A non-localized, non-versioned image resource called "duke.gif", in version 2_3 of the "corporate" library

corporate/2_3/duke.gif

__

basic

2_3

script.js

1_3_4.js

A non-localized, version 1.3.4 script resource called "script.js", in versioned 2_3

library called "basic".

basic/2_3/script.js/1_3_4.js

de

__

__

header.css

__

A non-versioned style resource called "header.css" localized for locale "de"

de/header.css

de_AT

__

__

footer.css

1_4_2.css

Version 1_4_2 of style resource "footer.css", localized for locale "de_AT"

de_AT/footer.css/1_4_2.css

zh

extraFancy

__

menu-bar.css

2_4.css

Version 2_4 of style resource called, "menu-bar.css" in non-versioned library, "extraFancy", localized for locale "zh"

zh/extraFancy/menu-bar.css/2_4.css

ja

mild

0_1

ajaxTransaction.js

__

Non-versioned script resource called, "ajaxTransaction.js", in version 0_1 of library called "mild", localized for locale "ja"

ja/mild/0_1/ajaxTransaction.js

de_ch

grassy

1_0

bg.png

1_0.png

Version 1_0 of image resource called "bg.png", in version 1_0 of library called "grassy" localized for locale "de_ch"

de_ch/grassy/1_0/bg.png/1_0.png

2.6.1.4. Libraries of Localized and Versioned Resources

An important feature of the resource handler is the ability for resources to be localized, versioned, and collected into libraries. The localization and versioning scheme is completely hidden behind the API of ResourceHandler and Resource and is not exposed in any way to the Jakarta Faces run-time.

The default implementation of ResourceHandler.createResource(), for all variants of that method, must implement the following to discover which actual resource will be encapsulated within the returned Resource instance. An implementation may perform caching of the resource metadata to improve performance if the ProjectStage is ProjectStage.Production.

Using the resourceName and libraryName arguments to createResource(), and the resource packaging scheme specified in Packaging Resources into the Web Application Root, Packaging Resources into the Classpath, and Resource Identifiers, discover the file or entry that contains the bytes of the resource. If there are multiple versions of the same library, and libraryVersion is not specified, the library with the highest version is chosen. If there are multiple versions of the same resource, and resourceVersion is not specified, the resource with the highest version is chosen. The algorithm is specified in pseudocode.

function createResource(resourceName, libraryName) {
    var resource = null;
    var resourceId = null;
    for (var contract : getLibraryContracts()) {
        resourceId = deriveResourceIdConsideringResourceLoaders(contract,
                resourceName, libraryName)
        if (null != resourceId) {
            resource = create the resource using the resourceId;
            return resource;
        }
    }

    // try without a contract
    resourceId = deriveResourceIdConsideringResourceLoaders(null,
            resourceName, libraryName)
    if (null != resourceId) {
        resource = create the resource using the resourceId;
    }
    return resource;
}

function deriveResourceIdConsideringResourceLoaders(contract,
        resourceName, libraryName) {
    var prefix = web app root resource prefix;
    var resourceLoader = web app resource loader;
    // these are shorthand for the prefix and resource loading
    // facility specified in Section 2.6.1.1. They are
    // not actual API per se.
    var resourceId = deriveResourceIdConsideringLocalePrefix(contract,
            prefix, resourceLoader, resourceName, libraryName);

    if (null == resourceId) {
        prefix = classpath resource prefix;
        resourceLoader = classpath resource loader;
        // these are shorthand for the prefix and resource
        // loading facility specified in Section 2.6.1.2. They are
        // not actual API per se.
        resourceId = deriveResourceIdConsideringLocalePrefix(contract,
                prefix, resourceLoader, resourceName, libraryName);
    }
    return resourceId;
}

function deriveResourceIdConsideringLocalePrefix(contract, prefix,
        resourceLoader, resourceName, libraryName) {
    var localePrefix = getLocalePrefix();
    var result = deriveResourceId(contract, prefix, resourceLoader,
            resourceName, libraryName, localePrefix);
    // If the application has been configured to have a localePrefix,
    // and the resource is not found, try to find it again,
    // without the localePrefix.
    if (null == result && null != localePrefix) {
        result = deriveResourceId(contract, prefix, resourceLoader,
                resourceName, libraryName, null);
    }
    return result;
}

function deriveResourceId(contract, prefix, resourceLoader,
        resourceName, libraryName, localePrefix) {
    var resourceVersion = null;
    var libraryVersion = null;
    var resourceId;
    if (null != localePrefix) {
        prefix = localePrefix + '/' + prefix;
    }
    if (null != contract) {
        prefix = contract + '/' + prefix;
    }

    if (null != libraryName) {
        // actual argument is
        // resourcesInContractInJar/resources/resourcesInContractInJar
        var libraryPaths = resourceLoader.getResourcePaths(
                prefix + '/' + libraryName);

        if (null != libraryPaths && !libraryPaths.isEmpty()) {
            libraryVersion = // execute the comment
            // Look in the libraryPaths for versioned libraries.
            // If one or more versioned libraries are found, take
            // the one with the highest version number as the value
            // of libraryVersion. If no versioned libraries
            // are found, let libraryVersion remain null.
        }
        if (null != libraryVersion) {
            libraryName = libraryName + '/' + libraryVersion;
        }
        var resourcePaths = resourceLoader.getResourcePaths(
            prefix + '/' + libraryName + '/' + resourceName);
        if (null != resourcePaths && !resourcePaths.isEmpty()) {
            resourceVersion = // execute the comment +
            // Look in the resourcePaths for versioned resources.
            // If one or more versioned resources are found, take
            // the one with the "highest" version number as the value
            // of resourceVersion. If no versioned libraries
            // are found, let resourceVersion remain null.
        }
        if (null != resourceVersion) {
            resourceId = prefix + '/' + libraryName + '/' +
                    resourceName + '/' + resourceVersion;
        }
        else {
            resourceId = prefix + '/' + libraryName + '/' + resourceName;
        }
    } // end of if (null != libraryName)
    else {
        // libraryName == null
        var resourcePaths = resourceLoader.getResourcePaths(
                prefix + '/' + resourceName);
        if (null != resourcePaths && !resourcePaths.isEmpty()) {
            resourceVersion = // execute the comment
            // Look in the resourcePaths for versioned resources.
            // If one or more versioned resources are found, take
            // the one with the "highest" version number as the value
            // of resourceVersion. If no versioned libraries
            // are found, let resourceVersion remain null.
        }
        if (null != resourceVersion) {
            resourceId = prefix + '/' + resourceName + '/' +
                    resourceVersion;
        } else {
            resourceId = prefix + '/' + resourceName;
        }
    } // end of else, when libraryName == null
    return resourceId;
}

function getLocalePrefix() {
    var localePrefix;
    var appBundleName = facesContext.application.messageBundle;
    if (null != appBundleName) {
        var locale =
            // If there is a viewRoot on the current facesContext,
            // use its locale.
            // Otherwise, use the locale of the application's ViewHandler
        ResourceBundle appBundle = ResourceBundle.getBundle(
                appBundleName, locale);
        localePrefix = appBundle.getString(ResourceHandler. LOCALE_PREFIX);
    }
    // Any MissingResourceException instances that are encountered
    // in the above code must be swallowed by this method, and null
    // returned;
    return localePrefix;
}

2.6.2. Rendering Resources

Resources such as images, stylesheets and scripts use the resource handling mechanism as outlined in Packaging Resources. So, for example:

<h:graphicImage library="common" name="images/planets.png" />
<h:graphicImage value="#{resource['common:images/planets.png']}" />

These entries render exactly the same markup. In addition to using the name and library attributes, stylesheet and script resources can be “relocated” to other parts of the view. For example, we could specify that a script resource be rendered within an HTML “head”, “body” or “form” element in the page.

2.6.2.1. Relocatable Resources

Relocatable resources are resources that can be told where to render themselves, and this rendered location may be different than the resource tag placement in the view. For example, a portion of the view may be described in the view declaration language as follows:

<!DOCTYPE html>
<html xmlns:h="jakarta.faces.html">
  <h:head>
    <title>Example View</title>
  </h:head>
  <h:body>
    <h:form>
      <h:outputScript library="jakarta.faces" name="faces.js" target="head" />
    </h:form>
  </h:body>
</html>

The example tag <h:outputScript> which extends from UIOutput refers to the example renderer, ScriptRenderer, implementing ComponentSystemEventListener, that listens for PostAddToViewEvent event types:

@ListenerFor(facesEventClass=PostAddToViewEvent.class,
        sourceClass=UIOutput.class)
public class ScriptRenderer extends Renderer
        implements ComponentSystemEventListener {...

Refer to Event and Listener Model. When the component for this resource is added to the view, the ScriptRenderer.processEvent() method adds the component to a facet (named by the target attribute) under the view root. using the UIViewRoot component resource methods as described in Methods.

The <h:head> and <h:body> tags refer to the renderers HeadRenderer and BodyRenderer respectively. They are described in the Standard HTML Renderkit documentation referred to in Standard HTML RenderKit Implementation. During the rendering phase, the encode methods for these renderers render the HTML “head” and “body” elements respectively. Then they render all component resources under the facet child (named by target) under the UIViewRoot using the UIViewRoot component resource methods as described in Methods.

Existing component libraries (with existing head and body components), that want to use this resource loading feature must follow the rendering requirements described in Standard HTML RenderKit Implementation.

2.6.2.2. Resource Rendering Using Annotations

Components and renderers may be declared as requiring a resource using the @ResourceDependency annotation. The implementation must scan for the presence of this annotation on the component that was added to the List of child components. Check for the presence of the annotation on the renderer for this component (if there is a renderer for the component). The annotation check must be done immediately after the component is added to the List. Refer to Component Tree Manipulation for detailed information.

2.7. Resource Library Contracts

A resource library contract is a resource library, as specified in the preceding section, except that instead of residing in the resources directory of the web-app root, or in the META-INF/resources JAR entry name in a JAR file, it resides in the contracts directory of the web-app root, or in the META-INF/contracts JAR entry name in a JAR file. When packaged in a JAR file, there is one additional packaging requirement: each resource library contract in the JAR must have a marker file. The name of the file is given by the value of the symbolic constant jakarta.faces.application.ResourceHandler.RESOURCE_CONTRACT_XML. This may be a zero length file, though future versions of the specification may use the file to declare the usage contract. The requirement to have a marker file enables implementations to optimize for faster deployment while still enabling automatic discovery of the available contracts.

Following is a listing of the entries in a JAR file containing two resource library contracts.

META-INF/contracts/
                  siteLayout/
                            jakarta.faces.contract.xml
                            topNav_template.xhtml
                            leftNav_foo.xhtml
                            styles.css
                            script.js
                            background.png
                  subSiteLayout/
                                jakarta.faces.contract.xml
                                sub_template.xhtml

All of the other packaging, encoding and decoding requirements are the same as for resource libraries.

See Resource Library Contracts Background for a non-normative overview of the feature, including a brief usage example.

3. User Interface Component Model

A Jakarta Faces user interface component is the basic building block for creating a Jakarta Faces user interface. A particular component represents a configurable and reusable element in the user interface, which may range in complexity from simple (such as a button or text field) to compound (such as a tree control or table). Components can optionally be associated with corresponding objects in the data model of an application, via value expressions.

Jakarta Faces also supports user interface components with several additional helper APIs:

  • Converters —Pluggable support class to convert the markup value of a component to and from the corresponding type in the model tier.

  • Events and Listeners —An event broadcast and listener registration model based on the design patterns of the JavaBeans Specification, version 1.0.1.

  • Validators —Pluggable support classes that can examine the local value of a component (as received in an incoming request) and ensure that it conforms to the business rules enforced by each Validator. Error messages for validation failures can be generated and sent back to the user during rendering.

The user interface for a particular page of a Jakarta Faces-based web application is created by assembling the user interface components for a particular request or response into a view. The view is a tree of classes that implement UIComponent. The components in the tree have parent-child relationships with other components, starting at the root element of the tree, which must be an instance of UIViewRoot. Components in the tree can be anonymous or they can be given a component identifier by the framework user. Components in the tree can be located based on component identifiers, which must be unique within the scope of the nearest ancestor to the component that is a naming container. For complex rendering scenarios, components can also be attached to other components as facets.

This chapter describes the basic architecture and APIs for user interface components and the supporting APIs.

3.1. UIComponent and UIComponentBase

The base abstract class for all user interface components is jakarta.faces.component.UIComponent. This class defines the state information and behavioral contracts for all components through a Java programming language API, which means that components are independent of a rendering technology such as Facelets. A standard set of components (described in Standard User Interface Components) that add specialized properties, attributes, and behavior, is also provided as a set of concrete subclasses.

Component writers, tool providers, application developers, and Jakarta Faces implementors can also create additional UIComponent implementations for use within a particular application. To assist such developers, a convenience subclass, jakarta.faces.component.UIComponentBase, is provided as part of Jakarta Faces. This class provides useful default implementations of nearly every UIComponent method, allowing the component writer to focus on the unique characteristics of a particular UIComponent implementation.

The following subsections define the key functional capabilities of Jakarta Faces user interface components.

3.1.1. Component Identifiers

public String getId();
public void setId(String componentId);

Every component may be named by a component identifier that must conform to the following rules:

  • They must start with a letter (as defined by the Character.isLetter() method).

  • Subsequent characters must be letters (as defined by the Character.isLetter() method), digits as defined by the Character.isDigit() method, dashes (‘-’), or underscores (‘_’).

To minimize the size of responses generated by Jakarta Faces, it is recommended that component identifiers be as short as possible.

If a component has been given an identifier, it must be unique in the namespace of the closest ancestor to that component that is a NamingContainer (if any).

3.1.2. Component Type

While not a property of UIComponent, the component-type is an important piece of data related to each UIComponent subclass that allows the Application instance to create new instances of UIComponent subclasses with that type. Please see Object Factories for more on component-type.

Component types starting with “jakarta.faces.” are reserved for use by the Jakarta Faces specification.

3.1.3. Component Family

public String getFamily();

Each standard user interface component class has a standard value for the component family, which is used to look up renderers associated with this component. Subclasses of a generic UIComponent class will generally inherit this property from its superclass, so that renderers who only expect the superclass will still be able to process specialized subclasses.

Component families starting with “jakarta.faces.” are reserved for use by the Jakarta Faces specification.

3.1.4. ValueExpression properties

Properties and attributes of standard concrete component classes may be value expression enabled. This means that, rather than specifying a literal value as the parameter to a property or attribute setter, the caller instead associates a ValueExpression (see ValueExpression) whose getValue() method must be called (by the property getter) to return the actual property value to be returned if no value has been set via the corresponding property setter. If a property or attribute value has been set, that value must be returned by the property getter (shadowing any associated value binding expression for this property).

Value binding expressions are managed with the following method calls:

public ValueExpression getValueExpression(String name);
public void setValueExpression(String name, ValueExpression expression);

where name is the name of the attribute or property for which to establish the value expression. The implementation of setValueExpression must detemine if the expression is a literal by calling ValueExpression.isLiteralText() on the expression argument. If the expression argument is literal text, then ValueExpression.getValue() must be called on the expression argument. The result must be used as the value argument, along with the name argument to this component’s getAttributes().put(name, value) method call. For the standard component classes defined by this specification, all attributes, and all properties other than id, parent, action, listener, actionListener, valueChangeListener, and validator are value expression enabled. The action, listener, actionListener, valueChangeListener, and validator attributes are method expression enabled.

In previous versions of this specification, this concept was called “value binding”. Methods and classes referring to this concept are deprecated, but remain implemented to preserve backwards compatibility.

public ValueBinding getValueBinding(String name);
public void setValueBinding(String name, ValueBinding binding);

Please consult the javadoc for these methods to learn how they are implemented in terms of the new “value expression” concept.

3.1.5. Component Bindings

A component binding is a special value expression that can be used to facilitate “wiring up” a component instance to a corresponding property of a JavaBean that is associated with the page, and wants to manipulate component instances programatically. It is established by calling setValueExpression() (see ValueExpression properties) with the special property name binding.

The specified ValueExpression must point to a read-write JavaBeans property of type UIComponent (or appropriate subclass). Such a component binding is used at two different times during the processing of a Faces Request:

  • When a component instance is first created (typically by virtue of being referenced by a tag in a page), the Jakarta Faces implementation will retrieve the ValueExpression for the name binding, and call getValue() on it. If this call returns a non-null UIComponent value (because the JavaBean programmatically instantiated and configured a component already), that instance will be added to the component tree that is being created. If the call returns null, a new component instance will be created, added to the component tree, and setValue() will be called on the ValueExpression (which will cause the property on the JavaBean to be set to the newly created component instance).

  • When a component tree is recreated during the Restore View phase of the request processing lifecycle, for each component that has a ValueExpression associated with the name “binding”, setValue() will be called on it, passing the recreated component instance.

Component bindings are often used in conjunction with JavaBeans that are dynamically instantiated via the Managed Bean Creation facility. If application developers place managed beans that are pointed at by component binding expressions in any scope other than request scope, the system cannot behave correctly. This is because placing it in a scope wider than request scope would require thread safety, since UIComponent instances depend on running inside of a single thread. There are also potentially negative impacts on memory management when placing a component binding in “session” or “view” scopes.

3.1.6. Client Identifiers

Client identifiers are used by Jakarta Faces implementations, as they decode and encode components, for any occasion when the component must have a client side name. Some examples of such an occasion are:

  • to name request parameters for a subsequent request from the Jakarta Faces-generated page.

  • to serve as anchors for client side scripting code.

  • to serve as anchors for client side accessibility labels.

public String getClientId(FacesContext context);
protected String getContainerClientId(FacesContext context);

The client identifier is derived from the component identifier (or the result of calling UIViewRoot.createUniqueId() if there is not one), and the client identifier of the closest parent component that is a NamingContainer according to the algorithm specified in the javadoc for UIComponent.getClientId(). The Renderer associated with this component, if any, will then be asked to convert this client identifier to a form appropriate for sending to the client. The value returned from this method must be the same throughout the lifetime of the component instance unless setId() is called, in which case it will be recalculated by the next call to getClientId().

3.1.7. Component Tree Manipulation

public UIComponent getParent();
public void setParent(UIComponent parent);

Components that have been added as children of another component can identify the parent by calling the getParent method. For the root node component of a component tree, or any component that is not part of a component tree, getParent will return null. In some special cases, such as transient components, it is possible that a component in the tree will return null from getParent(). The setParent() method should only be called by the List instance returned by calling the getChildren() method, or the Map instance returned by calling the getFacets() method, when child components or facets are being added, removed, or replaced.

public List<UIComponent> getChildren();

Return a mutable List that contains all of the child UIComponents for this component instance. The returned List implementation must support all of the required and optional methods of the List interface, as well as update the parent property of children that are added and removed, as described in the Javadocs for this method. Note that the add() methods have a special requirement to cause the PostAddToViewEvent method to be fired, as well as the processing of the ResourceDependency annotation. See the javadocs for getChildren() for details.

public int getChildCount();

A convenience method to return the number of child components for this component. [P2-start UIComponent.getChildCount requirements.] If there are no children, this method must return 0. The method must not cause the creation of a child component list, so it is preferred over calling getChildren().size() when there are no children. [P2-end]

3.1.8. Component Tree Navigation

public UIComponent findComponent(String expr);

Search for and return the UIComponent with an id that matches the specified search expression (if any), according to the algorithm described in the Javadocs for this method.

public Iterator<UIComponent> getFacetsAndChildren();

Return an immutable Iterator over all of the facets associated with this component (in an undetermined order), followed by all the child components associated with this component (in the order they would be returned by getChildren()).

public boolean invokeOnComponent(FacesContext context,
    String clientId, ContextCallback callback) throws FacesException;

Starting at this component in the view, search for the UIComponent whose getClientId() method returns a String that exactly matches the argument clientId using the algorithm specified in the Javadocs for this method. If such a UIComponent is found, call the invokeContextCallback() method on the argument callback passing the current FacesContext and the found UIComponent. Upon normal return from the callback, return true to the caller. If the callback throws an exception, it must be wrapped inside of a FacesException and re-thrown. If no such UIComponent is found, return false to the caller.

Special consideration should be given to the implementation of invokeOnComponent() for UIComponent classes that handle iteration, such as UIData. Iterating components manipulate their own internal state to handle iteration, and doing so alters the clientIds of components nested within the iterating component. Implementations of invokeOnComponent() must guarantee that any state present in the component or children is restored before returning. Please see the Javadocs for UIData.invokeOnComponent() for details.

The ContextCallback interface is specified as follows..

public interface ContextCallback {
  public void invokeContextCallback(
      FacesContext context, UIComponent target);
}

Please consult the Javadocs for more details on this interface.

public static UIComponent getCurrentComponent(FacesContext context);

Returns the UIComponent instance that is currently being processed.

public static UIComponent getCurrentCompositeComponent(
    FacesContext context);

Returns the closest ancestor component relative to getCurrentComponent that is a composite component, or null if no such component is exists.

public boolean visitTree(VisitContext context, VisitCallback callback);

Uses the visit API introduced in version 2 of the specification to perform a flexible and customizable visit of the tree from this instance and its children. Please see the package description for the package jakarta.faces.component.visit for the normative specification.

3.1.9. Facet Management

Jakarta Faces supports the traditional model of composing complex components out of simple components via parent-child relationships that organize the entire set of components into a tree, as described in Component Tree Manipulation. However, an additional useful facility is the ability to define particular subordinate components that have a specific role with respect to the owning component, which is typically independent of the parent-child relationship. An example might be a “data grid” control, where the children represent the columns to be rendered in the grid. It is useful to be able to identify a component that represents the column header and/or footer, separate from the usual child collection that represents the column data.

To meet this requirement, Jakarta Faces components offer support for facets, which represent a named collection of subordinate (but non-child) components that are related to the current component by virtue of a unique facet name that represents the role that particular component plays. Although facets are not part of the parent-child tree, they participate in request processing lifecycle methods, as described in Lifecycle Management Methods.

public Map<String, UIComponent> getFacets();

Return a mutable Map representing the facets of this UIComponent, keyed by the facet name.

public UIComponent getFacet(String name);

A convenience method to return a facet value, if it exists, or null otherwise. If the requested facet does not exist, no facets Map must not be created, so it is preferred over calling getFacets().get() when there are no Facets.

For easy use of components that use facets, component authors may include type-safe getter and setter methods that correspond to each named facet that is supported by that component class. For example, a component that supports a header facet of type UIHeader should have methods with signatures and functionality as follows:

public UIHeader getHeader() {
  return ((UIHeader) getFacet("header");
}

public void setHeader(UIHeader header) {
  getFacets().put("header", header);
}

3.1.10. Managing Component Behavior

UIComponentBase provides default implementations for the methods from the jakarta.faces.component.behavior.BehaviorHolder interface. UIComponentBase does not implement the jakarta.faces.component.behavior.BehaviorHolder interface, but it provides the default implementations to simplify subclass implemenations. Refer to Component Behavior Model for more information.

public void addBehavior(String eventName, Behavior behavior)

This method attaches a Behavior to the component for the specified eventName. The eventName must be one of the values in the Collection returned from getEventNames(). For example, it may be desired to have some behavior defined when a “click” event occurs. The behavior could be some client side behavior in the form of a script executing, or a server side listener executing.

public Collection<String> getEventNames()

Returns the logical event names that can be associated with behavior for the component.

public Map<String, List<Behavior>> getBehaviors()

Returns a Map defining the association of events and behaviors. They keys in the Map are event names.

public String getDefaultEventName()

Returns the default event name (if any) for the component.

3.1.11. Generic Attributes

public Map<String, Object> getAttributes();

The render-independent characteristics of components are generally represented as Jakarta Bean component properties with getter and setter methods (see Render-Independent Properties). In addition, components may also be associated with generic attributes that are defined outside the component implementation class. Typical uses of generic attributes include:

  • Specification of render-dependent characteristics, for use by specific Renderers.

  • General purpose association of application-specific objects with components.

The attributes for a component may be of any Java programming language object type, and are keyed by attribute name (a String). However, see State Saving Alternatives and Implications for implications of your application’s choice of state saving method on the classes used to implement attribute values.

Attribute names that begin with jakarta.faces are reserved for use by the Jakarta Faces specification. Names that begin with jakarta are reserved for definition through the Eclipse Foundation Process. Implementations are not allowed to define names that begin with jakarta.

The Map returned by getAttributes() must also support attribute-property transparency, which operates as follows:

  • When the get() method is called, if the specified attribute name matches the name of a readable JavaBeans property on the component implementation class, the value returned will be acquired by calling the appropriate property getter method, and wrapping Java primitive values (such as int) in their corresponding wrapper classes (such as java.lang.Integer) if necessary. If the specified attribute name does not match the name of a readable JavaBeans property on the component implementation class, consult the internal data-structure to in which generic attributes are stored. If no entry exists in the internal data-structure, see if there is a ValueExpression for this attribute name by calling getValueExpression(), passing the attribute name as the key. If a ValueExpression exists, call getValue() on it, returning the result. If an ELException is thrown wrap it in a FacesException and re-throw it.

  • When the put() method is called, if the specified attribute name matches the name of a writable JavaBeans property on the component implementation class, the appropriate property setter method will be called. If the specified attribute name does not match the name of a writable JavaBeans property, simply put the value in the data-structure for generic attributes.

  • When the remove() method is called, if the specified attribute name matches the name of a JavaBeans property on the component, an IllegalArgumentException must be thrown.

  • When the containsKey() method is called, if the specified attribute name matches the name of a JavaBeans property, return false. Otherwise, return true if and only if the specified attribute name exists in the internal data-structure for the generic attributes.

The Map returned by getAttributes() must also conform to the entire contract for the Map interface.

3.1.11.1. Special Attributes
UIComponent Constants
public static final String BEANINFO_KEY =
    "jakarta.faces.component.BEANINFO_KEY";

This is a key in the component attributes Map whose value is a java.beans.BeanInfo describing the composite component.

public static final String FACETS_KEY =
    "jakarta.faces.component.FACETS_KEY";

This is a key in the composite component BeanDescriptor whose value is a Map<PropertyDescriptor> that contains meta-information for the declared facets for the composite component.

public static final String COMPOSITE_COMPONENT_TYPE_KEY =
    "jakarta.faces.component.COMPOSITE_COMPONENT_TYPE";

This is a key in the composite component BeanDescriptor whose value is a ValueExpression that evaluates to the component-type of the composite component root.

public static final String COMPOSITE_FACET_NAME =
    "jakarta.faces.component.COMPOSITE_FACET_NAME";

This is a key in the Map<PropertyDescriptor> that is returned by using the key FACETS_KEY. The value of this constant is also used as the key in the Map returned from getFacets(). In this case, the value of this key is the facet (the UIPanel) that is the parent of all the components in the composite implementation section of the composite component VDL file.

Refer to the jakarta.faces.component.UIComponent Javadocs for more detailed information.

3.1.12. Render-Independent Properties

The render-independent characteristics of a user interface component are represented as JavaBean component properties, following JavaBeans naming conventions. Specifically, the method names of the getter and/or setter methods are determined using standard JavaBeans component introspection rules, as defined by java.beans.Introspector. The render-independent properties supported by all UIComponents are described in the following table:

Name Access Type Description

id

RW

String

The component identifier, as described in Component Identifiers.

parent

RW

UIComponent

The parent component for which this component is a child or a facet.

rendered

RW

boolean

A flag that, if set to true, indicates that this component should be processed during all phases of the request processing lifecycle. The default value is “true”.

rendererType

RW

String

Identifier of the Renderer instance (from the set of Renderer instances supported by the RenderKit associated with the component tree we are processing. If this property is set, several operations during the request processing lifecycle (such as decode and the encodeXxx family of methods) will be delegated to a Renderer instance of this type. If this property is not set, the component must implement these methods directly.

rendersChildren

RO

boolean

A flag that, if set to true, indicates that this component manages the rendering of all of its children components (so the Jakarta Faces implementation should not attempt to render them). The default implementation in UIComponentBase delegates this setting to the associated Renderer, if any, and returns false otherwise.

transient

RW

boolean

A flag that, if set to true, indicates that this component must not be included in the state of the component tree. The default implementation in UIComponentBase returns false for this property.

The method names for the render-independent property getters and setters must conform to the design patterns in the JavaBeans specification. See State Saving Alternatives and Implications for implications of your application’s choice of state saving method on the classes used to implement property values.

3.1.13. Component Specialization Methods

The methods described in this section are called by the Jakarta Faces implementation during the various phases of the request processing lifecycle, and may be overridden in a concrete subclass to implement specialized behavior for this component.

public boolean broadcast(FacesEvent event)
    throws AbortProcessingException;

The broadcast() method is called during the common event processing (see Common Event Processing) at the end of several request processing lifecycle phases. For more information about the event and listener model, see Event and Listener Model. Note that it is not necessary to override this method to support additional event types.

public void decode(FacesContext context);

This method is called during the Apply Request Values phase of the request processing lifecycle, and has the responsibility of extracting a new local value for this component from an incoming request. The default implementation in UIComponentBase delegates to a corresponding Renderer, if the rendererType property is set, and does nothing otherwise.

Generally, component writers will choose to delegate decoding and encoding to a corresponding Renderer by setting the rendererType property (which means the default behavior described above is adequate).

public void encodeAll(FacesContext context) throws IOException
public void encodeBegin(FacesContext context) throws IOException;
public void encodeChildren(FacesContext context) throws IOException;
public void encodeEnd(FacesContext context) throws IOException;

These methods are called during the Render Response phase of the request processing lifecycle. encodeAll() will cause this component and all its children and facets that return true from isRendered() to be rendered, regardless of the value of the getRendersChildren() return value. encodeBegin(), encodeChildren(), and encodeEnd() have the responsibility of creating the response data for the beginning of this component, this component’s children (only called if the rendersChildren property of this component is true), and the ending of this component, respectively. Typically, this will involve generating markup for the output technology being supported, such as creating an HTML <input> element for a UIInput component. For clients that support it, the encode methods might also generate client-side scripting code (such as JavaScript), and/or stylesheets (such as CSS). The default implementations in UIComponentBase encodeBegin() and encodeEnd() delegate to a corresponding Renderer, if the rendererType property is true, and do nothing otherwise. The default implementation in UIComponentBase encodeChildren() must iterate over its children and call encodeAll() for each child component. encodeBegin() must publish a PreRenderComponentEvent.

Generally, component writers will choose to delegate encoding to a corresponding Renderer, by setting the rendererType property (which means the default behavior described above is adequate).

public void queueEvent(FacesEvent event);

Enqueue the specified event for broadcast at the end of the current request processing lifecycle phase. Default behavior is to delegate this to the queueEvent() of the parent component, normally resulting in broadcast via the default behavior in the UIViewRoot lifecycle methods.

The component author can override any of the above methods to customize the behavior of their component.

3.1.14. Lifecycle Management Methods

The following methods are called by the various phases of the request processing lifecycle, and implement a recursive tree walk of the components in a component tree, calling the component specialization methods described above for each component. These methods are not generally overridden by component writers, but doing so may be useful for some advanced component implementations. See the javadocs for detailed information on these methods

In order to support the “component” implicit object (See Implicit Object ELResolver for Facelets and Programmatic Access), the following methods have been added to UIComponent

protected void pushComponentToEL(FacesContext context);
protected void popComponentFromEL(FacesContext context)

pushComponentToEL() and popComponentFromEL() must be called inside each of the lifecycle management methods in this section as specified in the javadoc for that method.

public void processRestoreState(FacesContext context, Object state);

Perform the component tree processing required by the Restore View phase of the request processing lifecycle for all facets of this component, all children of this component, and this component itself.

public void processDecodes(FacesContext context);

Perform the component tree processing required by the Apply Request Values phase of the request processing lifecycle for all facets of this component, all children of this component, and this component itself

public void processValidators(FacesContext context);

Perform the component tree processing required by the Process Validations phase of the request processing lifecycle for all facets of this component, all children of this component, and this component itself.

public void processUpdates(FacesContext context);

Perform the component tree processing required by the Update Model Values phase of the request processing lifecycle for all facets of this component, all children of this component, and this component itself.

public void processSaveState(FacesContext context);

Perform the component tree processing required by the state saving portion of the Render Response phase of the request processing lifecycle for all facets of this component, all children of this component, and this component itself.

3.1.15. Utility Methods

protected FacesContext getFacesContext();

Return the FacesContext instance for the current request.

protected Renderer getRenderer(FacesContext context);

Return the Renderer that is associated this UIComponent, if any, based on the values of the family and rendererType properties currently stored as instance data on the UIComponent.

protected void addFacesListener(FacesListener listener);
protected void removeFacesListener(FacesListener listener);

These methods are used to register and deregister an event listener. They should be called only by a public addXxxListener() method on the component implementation class, which provides typesafe listener registration.

public Map<String, String> getResourceBundleMap();

Return a Map of the ResourceBundle for this component. Please consult the Javadocs for more information.

3.2. Component Behavioral Interfaces

In addition to extending UIComponent, component classes may also implement one or more of the behavioral interfaces described below. Components that implement these interfaces must provide the corresponding method signatures and implement the described functionality.

3.2.1. ActionSource

The ActionSource interface defines a way for a component to indicate that wishes to be a source of ActionEvent events, including the ability invoke application actions (see Application Actions) via the default ActionListener facility (see ActionListener Property).

3.2.1.1. Properties

The following render-independent properties are added by the ActionSource interface:

Name Access Type Description

immediate

RW

boolean

A flag indicating that the default ActionListener should execute immediately (that is, during the Apply Request Values phase of the request processing lifecycle, instead of waiting for Invoke Application phase). The default value of this property must be false.

3.2.1.2. Methods

ActionSource adds no new processing methods.

3.2.1.3. Events

A component implementing ActionSource is a source of ActionEvent events. There are three important moments in the lifetime of an ActionEvent:

  • when an the event is created

  • when the event is queued for later processing

  • when the listeners for the event are notified

ActionEvent creation occurs when the system detects that the component implementing ActionSource has been activated. For example, a button has been pressed. This happens when the decode() processing of the Apply Request Values phase of the request processing lifecycle detects that the corresponding user interface control was activated.

ActionEvent queueing occurs immediately after the event is created.

Event listeners that have registered an interest in ActionEvents fired by this component (see below) are notified at the end of the Apply Request Values or Invoke Application phase, depending upon the immediate property of the originating UICommand.

ActionSource includes the following methods to register and deregister ActionListener instances interested in these events. See Event and Listener Model for more details on the event and listener model provided by Jakarta Faces.

public void addActionListener(ActionListener listener);
public void removeActionListener(ActionListener listener);

In addition to manually registered listeners, the Jakarta Faces implementation provides a default ActionListener that will process ActionEvent events during the Apply Request Values or Invoke Application phases of the request processing lifecycle. See Invoke Application for more information.

3.2.2. ActionSource2

The ActionSource2 interface extends ActionSource and provides a JavaBeans property analogous to the action property on ActionSource. This allows the ActionSource concept to leverage the Jakarta Expression Language API.

3.2.2.1. Properties

The following render-independent properties are added by the ActionSource interface:

Name Access Type Description

actionExpression

RW

jakarta.el.MethodExpression

A MethodExpression (see MethodExpression) that must (if non-null) point at an action method (see Application Actions). The specified method will be called during the Apply Request Values or Invoke Application phase of the request processing lifecycle, as described in Invoke Application.

3.2.2.2. Methods

ActionSource2 adds no new processing methods.

3.2.2.3. Events

ActionSource2 adds no new events.

3.2.3. NamingContainer

NamingContainer is a marker interface. Components that implement NamingContainer have the property that, for all of their children that have non-null component identifiers, all of those identifiers are unique. This property is enforced by the renderView() method on ViewHandler. Since this is just a marker interface, there are no properties, methods, or events. Among the standard components, UIForm and UIData implement NamingContainer. See UIForm and Section Methods “UIData” for details of how the NamingContainer concept is used in these two cases.

NamingContainer defines a public static final character constant, SEPARATOR_CHAR, that is used as default value to separate components of client identifiers, as well as the components of search expressions used by the findComponent() method see (Component Tree Navigation). The value of this constant must be a colon character (“:”), which is according to the HTML standard among the allowable values for the id and name attribute.

Use of this separator character in client identifiers rendered by Renderers can cause problems with CSS stylesheets that attach styles to a particular client identifier. For the Standard HTML RenderKit, this issue can be worked around by using the styleClass attribute to select CSS styles by class rather than by identifier, or by wrapping the section in a plain HTML <div> or <span> element containing the desired client identifier, or by escaping the colon character with a backslash in the CSS selector.

This separator character can be overridden to another character by the context initialization parameter named jakarta.faces.SEPARATOR_CHAR, for example an underscore character (“_”), but the page authors must then ensure to not use this exact character in the component identifiers themselves.

Component authors should never use the final character constant SEPARATOR_CHAR directly, but they should instead use UINamingContainer.getSeparatorChar(FacesContext) method to obtain the desired separator character, which can be either the overridden character or the default character of (“:”).

3.2.4. StateHolder

The StateHolder interface is implemented by UIComponent, Converter, FacesListener, and Validator classes that need to save their state between requests. UIComponent implements this interface to denote that components have state that must be saved and restored between requests.

3.2.4.1. Properties

The following render-independent properties are added by the StateHolder interface:

Name Access Type Description

transient

RW

boolean

A flag indicating whether this instance has decided to opt out of having its state information saved and restored. The default value for all standard component, converter, and validator classes that implement StateHolder must be false.

3.2.4.2. Methods

Any class implementing StateHolder must implement both the saveState() and restoreState() methods, since these two methods have a tightly coupled contract between themselves. In other words, if there is an inheritance hierarchy, it is not permissible to have the saveState() and restoreState() methods reside at different levels of the hierarchy.

public Object saveState(FacesContext context);
public void restoreState(FacesContext context,
    Object state) throws IOException;

Gets or restores the state of the instance as a Serializable Object.

If the class that implements this interface has references to Objects which also implement StateHolder (such as a UIComponent with a converter, event listeners, and/or validators) these methods must call the saveState() or restoreState() method on all those instances as well.

Any class implementing StateHolder must have a public no-args constructor.

If the state saving method is server, these methods may not be called.

If the class that implements this interface has references to Objects which do not implement StateHolder, these methods must ensure that the references are preserved. For example, consider class MySpecialComponent, which implements StateHolder, and keeps a reference to a helper class, MySpecialComponentHelper, which does not implement StateHolder. MySpecialComponent.saveState() must save enough information about MySpecialComponentHelper, so that when MySpecialComponent.restoreState() is called, the reference to MySpecialComponentHelper can be restored. The return from saveState() must be Serializable.

Since all of the standard user interface components listed in Standard User Interface Components” extend from UIComponent, they all implement the StateHolder interface. In addition, the standard Converter and Validator classes that require state to be saved and restored also implement StateHolder.

3.2.4.3. Events

StateHolder does not originate any standard events.

3.2.5. PartialStateHolder

PartialStateHolder extends StateHolder and adds a usage contract for components that wish to take part in the partial state saving mechanism introduced in version 2.0. Implementations of this interface should use the jakarta.faces.component.StateHelper instance returned from UIComponent.getStateHelper() to store stateful component information that otherwise would have been stored as instance variables on the class implementing PartialStateHolder.

3.2.5.1. Properties

PartialStateHolder adds no properties to the StateHolder contract

3.2.5.2. Methods

The following methods support the partial state saving feature:

void clearInitialState();
boolean initialStateMarked();
void markInitialState();

These methods allow the state saving feature to determine if the component is in its initial state or not, and to set the flag indicating this condition of existence. The Javadocs for these methods specify the conditions under which these methods are invoked.

3.2.5.3. Events

PartialStateHolder does not originate any standard events.

3.2.6. ValueHolder

ValueHolder is an interface that may be implemented by any concrete UIComponent that wishes to support a local value, as well as access data in the model tier via a value expression , and support conversion between String and the model tier data’s native data type.

3.2.6.1. Properties

The following render-independent properties are added by the ValueHolder interface:

Name Access Type Description

converter

RW

Converter

The Converter (if any) that is registered for this UIComponent.

value

RW

Object

First consult the local value property of this component. If non-null return it. If the local value property is null, see if we have a ValueExpression for the value property. If so, return the result of evaluating the property, otherwise return null.

localValue

RO

Object

allows any value set by calling setValue() to be returned, without potentially evaluating a ValueExpression the way that getValue() will do

Like nearly all component properties, the value property may have a value binding expression (see ValueExpression properties) associated with it. If present (and if there is no value set directly on this component), such an expression is utilized to retrieve a value dynamically from a model tier object during Render Response Phase of the request processing lifecycle. In addition, for input components, the value expression is used during Update Model Values phase (on the subsequent request) to push the possibly updated component value back to the model tier object.

The Converter property is used to allow the component to know how to convert the model type from the String format provided by the Servlet API to the proper type in the model tier.

The Converter property must be inspected for the presence of ResourceDependency and ResourceDependencies annotations as described in the Javadocs for the setConverter method.

3.2.6.2. Methods

ValueHolder adds no methods.

3.2.6.3. Events

ValueHolder does not originate any standard events.

3.2.7. EditableValueHolder

The EditableValueHolder interface (extends ValueHolder, see ValueHolder) describes additional features supported by editable components, including ValueChangeEvents and Validators.

3.2.7.1. Properties

The following render-independent properties are added by the EditableValueHolder interface:

Name Access Type Description

immediate

RW

boolean

Flag indicating that conversion and validation of this component’s value should occur during Apply Request Values phase instead of Process Validations phase.

localValueSet

RW

boolean

Flag indicating whether the value property has been set.

required

RW

boolean

Is the user required to provide a non-empty value for this component? Default value must be false.

submittedValue

RW

Object

The submitted, unconverted, value of this component. This property should only be set by the decode() method of this component, or its corresponding Renderer, or by the validate method of this component. This property should only be read by the validate() method of this component.

valid

RW

boolean

A flag indicating whether the local value of this component is valid (that is, no conversion error or validation error has occurred).

3.2.7.2. Methods

The following methods support the validation functionality performed during the Process Validations phase of the request processing lifecycle:

public void addValidator(Validator validator);
public void removeValidator(Validator validator);

The addValidator() and removeValidator() methods are used to register and deregister additional external Validator instances that will be used to perform correctness checks on the local value of this component.

If the validator property is not null, the method it points at must be called by the processValidations() method, after the validate() method of all registered Validators is called.

The addValidator’s Validator argument must be inspected for the presense of the ResourceDependency and ResourceDependencies annotations as described in the Javadocs for the addValidator method.

3.2.7.3. Events

EditableValueHolder is a source of ValueChangeEvent, PreValidateEvent and PostValidate events. These are emitted during calls to validate(), which happens during the Process Validations phase of the request processing lifecycle. The PreValidateEvent is published immediately before the component gets validated. PostValidate is published after validation has occurred, regardless if the validation was successful or not. If the validation for the component did pass successfully, and the previous value of this component differs from the current value, the ValueChangeEvent is published. The following methods allow listeners to register and deregister for ValueChangeEvents. See Event and Listener Model for more details on the event and listener model provided by Jakarta Faces.

public void addValueChangeListener(ValueChangeListener listener);
public void removeValueChangeListener(ValueChangeListener listener);

In addition to the above listener registration methods, If the valueChangeListener property is not null, the method it points at must be called by the broadcast() method, after the processValueChange() method of all registered ValueChangeListeners is called.

3.2.8. SystemEventListenerHolder

Classes that implement this interface agree to maintain a list of SystemEventListener instances for each kind of SystemEvent they can generate. This interface enables arbitrary Objects to act as the source for SystemEvent instances.

3.2.8.1. Properties

This interface contains no JavaBeans properties

3.2.8.2. Methods

The following method gives the Jakarta Faces runtime access to the list of listeners stored by this instance.:

public List<FacesLifecycleListener> getListenersForEventClass(
    Class<? extends SystemEvent> facesEventClass);

During the processing for Application.publishEvent(), if the source argument to that method implements SystemEventListenerHolder, the getListenersForEventClass() method is invoked on it, and each listener in the list is given an opportunity to process the event, as specified in the javadocs for Application.publishEvent().

3.2.8.3. Events

While the class that implements SystemEventListenerHolder is indeed a source of events, it is a call to Application.publishEvent() that causes the event to actually be emitted. In the interest of maximum flexibility, this interface does not define how listeners are added, removed, or stored. See Event and Listener Model for more details on the event and listener model provided by Jakarta Faces.

3.2.9. ClientBehaviorHolder

Components must implement the ClientBehaviorHolder interface to add the ability for attaching ClientBehavior instances (see Component Behavior Model). Components that extend UIComponentBase only need to implement the getEventNames() method and specify "implements ClientBehaviorHolder". UIComponentBase provides base implementations for all other methods. The concrete HTML component classes that come with Jakarta Faces implement the ClientBehaviorHolder interface.

public void addClientBehavior(String eventName, ClientBehavior behavior);

Attach a ClientBehavior to a component implementing this ClientBehaviorHolder interface for the specified event. A default implementation of this method is provided in UIComponentBase to make it easier for subclass implementations to add behaviors.

public Collection<String> getEventNames();

Return a Collection of logical event names that are supported by the component implementing this ClientBehaviorHolder interface. The Collection must be non null and unmodifiable.

public Map<String, List<ClientBehavior>> getClientBehaviors();

Return a Map containing the event-client behavior association. Each event in the Map may contain one or more ClientBehavior instances that were added via the addClientBehavior() method.

Each key value in this Map must be one of the event names in the Collection returned from getEventNames().

public String getDefaultEventName();

Return the default event name for this component behavior if the component defines a default event.

3.3. Conversion Model

This section describes the facilities provided by Jakarta Faces to support type conversion between server-side Java objects and their (typically String-based) representation in presentation markup.

3.3.1. Overview

A typical web application must constantly deal with two fundamentally different viewpoints of the underlying data being manipulated through the user interface:

  • The model view—Data is typically represented as Java programming language objects (often JavaBeans components), with data represented in some native Java programming language datatype. For example, date and time values might be represented in the model view as instances of java.util.Date.

  • The presentation view—Data is typically represented in some form that can be perceived or modified by the user of the application. For example, a date or type value might be represented as a text string, as three text strings (one each for month/date/year or one each for hour/minute/second), as a calendar control, associated with a spin control that lets you increment or decrement individual elements of the date or time with a single mouse click, or in a variety of other ways. Some presentation views may depend on the preferred language or locale of the user (such as the commonly used mm/dd/yy and dd/mm/yy date formats, or the variety of punctuation characters in monetary amount presentations for various currencies).

To transform data formats between these views, Jakarta Faces provides an ability to plug-in an optional Converter for each ValueHolder, which has the responsibility of converting the internal data representation between the two views. The application developer attaches a particular Converter to a particular ValueHolder by calling setConverter, passing an instance of the particular converter. A Converter implementation may be acquired from the Application instance (see Object Factories) for your application.

3.3.2. Converter

Jakarta Faces provides the jakarta.faces.convert.Converter interface to define the behavioral characteristics of a Converter. Instances of implementations of this interface are either identified by a converter identifier, or by a class for which the Converter class asserts that it can perform successful conversions, which can be registered with, and later retrieved from, an Application, as described in Object Factories.

Often, a Converter will be an object that requires no extra configuration information to perform its responsibilities. However, in some cases, it is useful to provide configuration parameters to the Converter (such as a java.text.DateFormat pattern for a Converter that supports java.util.Date model objects). Such configuration information will generally be provided via JavaBeans properties on the Converter instance.

Converter implementations should be programmed so that the conversions they perform are symmetric. In other words, if a model data object is converted to a String (via a call to the getAsString method), it should be possible to call getAsObject and pass it the converted String as the value parameter, and return a model data object that is semantically equal to the original one. In some cases, this is not possible. For example, a converter that uses the formatting facilities provided by the java.text.Format class might create two adjacent integer numbers with no separator in between, and in this case the Converter could not tell which digits belong to which number.

For UIInput and UIOutput components that wish to explicitly select a Converter to be used, a new Converter instance of the appropriate type must be created, optionally configured, and registered on the component by calling setConverter(). Otherwise, the Jakarta Faces implementation will automatically create new instances based on the data type being converted, if such Converter classes have been registered. In either case, Converter implementations need not be threadsafe, because they will be used only in the context of a single request processing thread.

The following two method signatures are defined by the Converter interface:

public Object getAsObject(FacesContext context,
    UIComponent component, String value) throws ConverterException;

This method is used to convert the presentation view of a component’s value (typically a String that was received as a request parameter) into the corresponding model view. It is called during the Apply Request Values phase of the request processing lifecycle.

public String getAsString(FacesContext context,
    UIComponent component, Object value) throws ConverterException;

This method is used to convert the model view of a component’s value (typically some native Java programming language class) into the presentation view (typically a String that will be rendered in some markup language. It is called during the Render Response phase of the request processing lifecycle.

If the class implementing Converter has a ResourceDependency annotation or a ResourceDependencies annotation, the action described in the Javadocs for the Converter interface must be followed when ValueHolder.setConverter is called.

3.3.3. Standard Converter Implementations

Jakarta Faces provides a set of standard Converter implementations. A Jakarta Faces implementation must register the DateTime and Number converters by name with the Application instance for this web application, as described in the table below. This ensures that the converters are available for subsequent calls to Application.createConverter(). Each concrete implementation class must define a static final String constant CONVERTER_ID whose value is the standard converter id under which this Converter is registered.

The following converter id values must be registered to create instances of the specified Converter implementation classes:

  • jakarta.faces.BigDecimal —An instance of jakarta.faces.convert.BigDecimalConverter (or a subclass of this class).

  • jakarta.faces.BigInteger —An instance of jakarta.faces.convert.BigIntegerConverter (or a subclass of this class).

  • jakarta.faces.Boolean —An instance of jakarta.faces.convert.BooleanConverter (or a subclass of this class).

  • jakarta.faces.Byte —An instance of jakarta.faces.convert.ByteConverter (or a subclass of this class).

  • jakarta.faces.Character —An instance of jakarta.faces.convert.CharacterConverter (or a subclass of this class).

  • jakarta.faces.DateTime —An instance of jakarta.faces.convert.DateTimeConverter (or a subclass of this class).

  • jakarta.faces.Double —An instance of jakarta.faces.convert.DoubleConverter (or a subclass of this class).

  • jakarta.faces.Float —An instance of jakarta.faces.convert.FloatConverter (or a subclass of this class).

  • jakarta.faces.Integer —An instance of jakarta.faces.convert.IntegerConverter (or a subclass of this class).

  • jakarta.faces.Long —An instance of jakarta.faces.convert.LongConverter (or a subclass of this class).

  • jakarta.faces.Number —An instance of jakarta.faces.convert.NumberConverter (or a subclass of this class).

  • jakarta.faces.Short —An instance of jakarta.faces.convert.ShortConverter (or a subclass of this class).

See the Javadocs for these classes for a detailed description of the conversion operations they perform, and the configuration properties that they support.

A Jakarta Faces implementation must register converters for all of the following classes using the by-type registration mechanism:

  • java.math.BigDecimal, and java.math.BigDecimal.TYPE —An instance of jakarta.faces.convert.BigDecimalConverter (or a subclass of this class).

  • java.math.BigInteger, and java.math.BigInteger.TYPE —An instance of jakarta.faces.convert.BigIntegerConverter (or a subclass of this class).

  • java.lang.Boolean, and java.lang.Boolean.TYPE —An instance of jakarta.faces.convert.BooleanConverter (or a subclass of this class).

  • java.lang.Byte, and java.lang.Byte.TYPE — An instance of jakarta.faces.convert.ByteConverter (or a subclass of this class).

  • java.lang.Character, and java.lang.Character.TYPE —An instance of jakarta.faces.convert.CharacterConverter (or a subclass of this class).

  • java.lang.Double, and java.lang.Double.TYPE —An instance of jakarta.faces.convert.DoubleConverter (or a subclass of this class).

  • java.lang.Float, and java.lang.Float.TYPE —An instance of jakarta.faces.convert.FloatConverter (or a subclass of this class).

  • java.lang.Integer, and java.lang.Integer.TYPE —An instance of jakarta.faces.convert.IntegerConverter (or a subclass of this class).

  • java.lang.Long, and java.lang.Long.TYPE — An instance of jakarta.faces.convert.LongConverter (or a subclass of this class).

  • java.lang.Short, and java.lang.Short.TYPE —An instance of jakarta.faces.convert.ShortConverter (or a subclass of this class).

  • java.lang.Enum, and java.lang.Enum.TYPE — An instance of jakarta.faces.convert.EnumConverter (or a subclass of this class).

See the Javadocs for these classes for a detailed description of the conversion operations they perform, and the configuration properties that they support.

A compliant implementation must allow the registration of a converter for class java.lang.String and java.lang.String.TYPE that will be used to convert values for these types.

3.4. Event and Listener Model

This section describes how Jakarta Faces provides support for generating and handling user interface events and system events.

3.4.1. Overview

Jakarta Faces implements a model for event notification and listener registration based on the design patterns in the JavaBeans Specification, version 1.0.1. This is similar to the approach taken in other user interface toolkits, such as the Swing Framework included in the JDK.

A UIComponent subclass may choose to emit events that signify significant state changes, and broadcast them to listeners that have registered an interest in receiving events of the type indicated by the event’s implementation class. At the end of several phases of the request processing lifecycle, the Jakarta Faces implementation will broadcast all of the events that have been queued to interested listeners. Jakarta Faces also defines system events. System events are events that are not specific to any particular application, but rather stem from specific points in time of running a Jakarta Faces application. The following UML class diagram illustrates the key players in the event model. Boxes shaded in gray indicate classes or interfaces defined outside of the jakarta.faces.event package.