Skip to content

Latest commit

 

History

History
3595 lines (2877 loc) · 133 KB

UserInterfaceComponentModel.adoc

File metadata and controls

3595 lines (2877 loc) · 133 KB

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.

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.

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).

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.

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.

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.

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.

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().

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]

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.

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);
}

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.

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.

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.

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.

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.

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.

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.

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.

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).

The ActionSource interface also provides a JavaBeans actionExpression property analogous to the action property. This allows the ActionSource concept to leverage the Jakarta Expression Language API.

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.

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.

Methods

ActionSource adds no new processing methods.

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.

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 (“:”).

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.

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.

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.

Events

StateHolder does not originate any standard events.

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.

Properties

PartialStateHolder adds no properties to the StateHolder contract

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.

Events

PartialStateHolder does not originate any standard events.

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.

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.

Methods

ValueHolder adds no methods.

Events

ValueHolder does not originate any standard events.

EditableValueHolder

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

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).

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.

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.

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.

Properties

This interface contains no JavaBeans properties

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().

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.

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.

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.

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.

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.

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).

  • jakarta.faces.UUID —An instance of jakarta.faces.convert.UUIDConverter (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).

  • java.lang.UUID, and java.lang.UUID.TYPE — An instance of jakarta.faces.convert.UUIDConverter (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.

Event and Listener Model

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

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.

Faces Event Package

Application Events

Application events are events that are specific to a particular application. Application events are the standard events that have been in Jakarta Faces from the beginning.

Event Classes

All events that are broadcast by Jakarta Faces user interface components must extend the jakarta.faces.event.FacesEvent abstract base class. The parameter list for the constructor(s) of this event class must include a UIComponent, which identifies the component from which the event will be broadcast to interested listeners. The source component can be retrieved from the event object itself by calling getComponent. Additional constructor parameters and/or properties on the event class can be used to relay additional information about the event.

In conformance to the naming patterns defined in the JavaBeans Specification, event classes typically have a class name that ends with Event. It is recommended that application event classes follow this naming pattern as well.

The component that is the source of a FacesEvent can be retrieved via this method:

public UIComponent getComponent();

FacesEvent has a phaseId property (of type PhaseId, see Phase Identifiers) used to identify the request processing lifecycle phase after which the event will be delivered to interested listeners.

public PhaseId getPhaseId();
public void setPhaseId(PhaseId phaseId);

If this property is set to PhaseId.ANY_PHASE (which is the default), the event will be delivered at the end of the phase in which it was enqueued.

To facilitate general management of event listeners in Jakarta Faces components, a FacesEvent implementation class must support the following methods:

public abstract boolean isAppropriateListener(FacesListener listener);
public abstract void processListener(FacesListener listener);

The isAppropriateListener() method returns true if the specified FacesListener is a relevant receiver of this type of event. Typically, this will be implemented as a simple “instanceof” check to ensure that the listener class implements the FacesListener subinterface that corresponds to this event class

The processListener() method must call the appropriate event processing method on the specified listener. Typically, this will be implemented by casting the listener to the corresponding FacesListener subinterface and calling the appropriate event processing method, passing this event instance as a parameter.

public void queue();

The above convenience method calls the queueEvent() method of the source UIComponent for this event, passing this event as a parameter.

Jakarta Faces includes two standard FacesEvent subclasses, which are emitted by the corresponding standard UIComponent subclasses described in the following chapter.

  • ActionEvent —Emitted by a UICommand component when the user activates the corresponding user interface control (such as a clicking a button or a hyperlink).

  • ValueChangeEvent —Emitted by a UIInput component (or appropriate subclass) when a new local value has been created, and has passed all validations.

Listener Classes

For each event type that may be emitted, a corresponding listener interface must be created, which extends the jakarta.faces.event.FacesListener interface. The method signature(s) defined by the listener interface must take a single parameter, an instance of the event class for which this listener is being created. A listener implementation class will implement one or more of these listener interfaces, along with the event handling method(s) specified by those interfaces. The event handling methods will be called during event broadcast, one per event.

In conformance to the naming patterns defined in the JavaBeans Specification, listener interfaces have a class name based on the class name of the event being listened to, but with the word Listener replacing the trailing Event of the event class name (thus, the listener for a FooEvent would be a FooListener). It is recommended that application event listener interfaces follow this naming pattern as well.

Corresponding to the two standard event classes described in the previous section, Jakarta Faces defines two standard event listener interfaces that may be implemented by application classes:

  • ActionListener —a listener that is interested in receiving ActionEvent events.

  • ValueChangeListener —a listener that is interested in receiving ValueChangeEvent events.

Phase Identifiers

As described in Common Event Processing, event handling occurs at the end of several phases of the request processing lifecycle. In addition, a particular event must indicate, through the value it returns from the getPhaseId() method, the phase in which it wishes to be delivered. This indication is done by returning an instance of jakarta.faces.event.PhaseId. The class defines a typesafe enumeration of all the legal values that may be returned by getPhaseId(). In addition, a special value (PhaseId.ANY_PHASE) may be returned to indicate that this event wants to be delivered at the end of the phase in which it was queued.

Listener Registration

A concrete UIComponent subclass that emits events of a particular type must include public methods to register and deregister a listener implementation. In order to be recognized by development tools, these listener methods must follow the naming patterns defined in the JavaBeans Specification. For example, for a component that emits FooEvent events, to be received by listeners that implement the FooListener interface, the method signatures (on the component class) must be:

public void addFooListener(FooListener listener);
public FooListener[] getFooListeners();
public void removeFooListener(FooListener listener);

The application (or other components) may register listener instances at any time, by calling the appropriate add method. The set of listeners associated with a component is part of the state information that Jakarta Faces saves and restores. Therefore, listener implementation classes must have a public zero-argument constructor, and may implement StateHolder (see StateHolder) if they have internal state information that needs to be saved and restored.

The UICommand and UIInput standard component classes include listener registration and deregistration methods for event listeners associated with the event types that they emit. The UIInput methods are also inherited by UIInput subclasses, including UISelectBoolean, UISelectMany, and UISelectOne.

Event Queueing

During the processing being performed by any phase of the request processing lifecycle, events may be created and queued by calling the queueEvent() method on the source UIComponent instance, or by calling the queue() method on the FacesEvent instance itself. As described in Common Event Processing, at the end of certain phases of the request processing lifecycle, any queued events will be broadcast to interested listeners in the order that the events were originally queued.

Deferring event broadcast until the end of a request processing lifecycle phase ensures that the entire component tree has been processed by that state, and that event listeners all see the same consistent state of the entire tree, no matter when the event was actually queued.

Event Broadcasting

As described in Common Event Processing, at the end of each request processing lifecycle phase that may cause events to be queued, the lifecycle management method of the UIViewRoot component at the root of the component tree will iterate over the queued events and call the broadcast() method on the source component instance to actually notify the registered listeners. See the Javadocs of the broadcast() method for detailed functional requirements.

During event broadcasting, a listener processing an event may:

  • Examine or modify the state of any component in the component tree.

  • Add or remove components from the component tree.

  • Add messages to be returned to the user, by calling addMessage on the FacesContext instance for the current request.

  • Queue one or more additional events, from the same source component or a different one, for processing during the current lifecycle phase.

  • Throw an AbortProcessingException, to tell the Jakarta Faces implementation that no further broadcast of this event should take place.

  • Call renderResponse() on the FacesContext instance for the current request. This tells the Jakarta Faces implementation that, when the current phase of the request processing lifecycle has been completed, control should be transferred to the Render Response phase.

  • Call responseComplete() on the FacesContext instance for the current request. This tells the Jakarta Faces implementation that, when the current phase of the request processing lifecycle has been completed, processing for this request should be terminated (because the actual response content has been generated by some other means).

System Events

System Events represent specific points in time for a Jakarta Faces application. PhaseEvents also represent specific points in time in a Jakarta Faces application, but the granularity they offer is not as precise as System Events. For more on PhaseEvents, please see PhaseEvent.

Event Classes

All system events extend from the base class SystemEvent. SystemEvent has a similar API to FacesEvent, but the source of the event is of type Object (instead of UIComponent ), SystemEvent has no PhaseId property and SystemEvent has no queue() method because SystemEvents are never queued. SystemEvent shares isAppropriateListener() and processListener() with FacesEvent. For the specification of these methods see Event Classes.

System events that originate from or are associated with specific component instances should extend from ComponentSystemEvent, which extends SystemEvent and adds a getComponent() method, as specififed in Event Classes.

The specification defines the following SystemEvent subclasses, all in package jakarta.faces.event.

  • ExceptionQueuedEvent indicates a non-expected Exception has been thrown. Please see ExceptionHandler for the normative specification.

  • PostConstructApplicationEvent must be published immediately after application startup. Please see Application Startup Behavior for the normative specification.

  • PreDestroyApplicationEvent must be published as immediately before application shutdown. Please see Application Shutdown Behavior for the normative specification

  • PostKeepFlashEvent This event must be published by a call to Application.publishEvent() when a value is kept in the flash.

  • PostPutFlashEvent This event must be published by a call to Application.publishEvent() when a value is stored in the flash.

  • PreClearFlashEvent This event must be published by a call to Application.publishEvent() when a before the flash is cleared.

  • PreRemoveFlashEvent This event must be published by a call to Application.publishEvent() when a value is removed from the flash.

The specification defines the following ComponentSystemEvent classes, all in package jakarta.faces.event.

  • PostAddToViewEvent indicates that the source component has just been added to the view. Please see Component Tree Manipulation for a reference to the normative specification.

  • PostConstructViewMapEvent indicates that the Map that is the view scope has just been created. Please see, the UIViewRoot Events for a reference to the normative specification.

  • PostRenderViewEvent indicates that the UIViewRoot source component has just been rendered. Please see Render Response for the normative specification.

  • PostRestoreStateEvent indicates that an individual component instance has just had its state restored. Please see the UIViewRoot Events for a reference to the normative specification.

  • PostValidateEvent indicates that an individual component instance has just been validated. Please see the EditableValueHolder Events for the normative specification.

  • PreDestroyViewMapEvent indicates that the Map that is the view scope is about to be destroyed. Please see, the UIViewRoot Properties for the normative specification.

  • PreRenderComponentEvent indicates that the source component is about to be rendered. Please see Component Tree Manipulation for a reference to the normative specification.

  • PreRenderViewEvent indicates that the UIViewRoot source component is about to be rendered. Please see Render Response for the normative specification.

  • PreValidateEvent indicates that an individual component instance is about to be validated. Please see the EditableValueHolder Events for the normative specification.

Listener Classes

Unlike application events, the creation of new event types for system events does not require the creation of new listener interfaces. All SystemEvent types can be listened for by listeners that implement jakarta.faces.event.SystemEventListener. Please see the javadocs for that class for the complete specification.

As a developer convenience, the listener interface ComponentSystemEventListener has been defined for those cases when a SystemEventListener is being attached to a specific UIComponent instance. ComponentSystemEventListener lacks the isListenerForSource() method because it is implcictly defined by virture of the listener being added to a specific component instance.

Programmatic Listener Registration

System events may be listened for at the Application level, using Application.subscribeToEvent() or at the component level, by calling subscribeToEvent() on a specific component instance. The specification for Application.subscribeToEvent() may be found in System Event Methods.

The following methods are defined on UIComponent to support per-component system events.

public void subscribeToEvent(Class<? extends SystemEvent> eventClass,
    ComponentSystemEventListener componentListener);
public void unsubscribeFromEvent(Class<? extends SystemEvent> eventClass,
    ComponentSystemEventListener componentListener);

See the javadoc for UIComponent for the normative specification of these methods.

In addition to the above methods, the @ListenerFor and @ListenersFor annotations allow components, renderers, validators and converters to declare that they want to register for system events. Please see the javadocs for those annotations for the complete specification.

Declarative Listener Registration

Page authors can subscribe to events using the <f:event/> tag. This tag will allow the application developer to specify the method to be called when the specifed event fires for the component of which the tag is a child. One example of the tag usage is as follows:

<h:form>
  <f:event type="postAddToView"
           listener="#{dynamicFormBacking.populateFields}" />
</h:form>

The type attribute specifies the type of event, and can be any of the specification-defined events or one of any user-defined events, but must be a ComponentSystemEvent, using either the short-hand name for the event or the fully-qualified class name (e.g., com.foo.app.event.CustomEvent). If the event can not be found, a FacesException listing the offending event type will be thrown. Please see the VDLDocs for the <f:event /> tag for the normative specification of the declarative event feature.

The method signature for the MethodExpression pointed to by the listener attribute must match the signature of jakarta.faces.event.ComponentSystemEventListener.processEvent(), which is:

public void processEvent(jakarta.faces.event.ComponentSystemEvent event)
    throws AbortProcessingException
Listener Registration By Annotation

The ListenerFor and ListenersFor annotations can be applied to components and rendererers. Classes tagged with the ListenerFor annotation are installed as listeners. The ListenersFor annotation is a container annotation tp specify multiple ListenerFor annotations for a single class. Please refer to the Javadocs for the ListenerFor and ListenersFor classes for more details.

Listener Registration By Application Configuration Resources

A <system-event-listener> element, within the <application> element of an application configuration resource, declares an application scoped listener and causes a call to Application.subscribeToEvent().

Event Broadcasting

System events are broadcast immediately by calls to Application.publishEvent() Please see System Event Methods for the normative specification of publishEvent().

Validation Model

This section describes the facilities provided by Jakarta Faces for validating user input.

Overview

Jakarta Faces supports a mechanism for registering zero or more validators on each EditableValueHolder component in the component tree. A validator’s purpose is to perform checks on the local value of the component, during the Process Validations phase of the request processing lifecycle. In addition, a component may implement internal checking in a validate method that is part of the component class.

Validator Classes

A validator must implement the jakarta.faces.validator.Validator interface, which contains a validate() method signature.

public void validate(FacesContext context,
    UIComponent component, Object value);

General purpose validators may require configuration values in order to define the precise check to be performed. For example, a validator that enforces a maximum length might wish to support a configurable length limit. Such configuration values are typically implemented as JavaBeans component properties, and/or constructor arguments, on the Validator implementation class. In addition, a validator may elect to use generic attributes of the component being validated for configuration information.

Jakarta Faces includes implementations of several standard validators, as described in Standard Validator Implementations.

Validation Registration

The EditableValueHolder interface (implemented by UIInput) includes an addValidator method to register an additional validator for this component, and a removeValidator method to remove an existing registration. Please see the javadocs for EditableValueHolder.addValidator().

The application (or other components) may register validator instances at any time, by calling the addValidator method. The set of validators associated with a component is part of the state information that Jakarta Faces saves and restores. Validators that wish to have configuration properties saved and restored must also implement StateHolder (see StateHolder).

In addition to validators which are registered explicitly on the component, either through the Java API or in the view markup, zero or more “default validators” can be declared in the application configuration resources, which will be registered on all UIInput instances in the component tree unless explicitly disabled. The default validators are appended after any locally defined validators once the EditableValueHolder is populated and added to the component tree. A default validator must not be added to a UIInput if a validator having the same id is already present.

The typical way of registering a default validator id is by declaring it in a configuration resource, as follows:

<faces-config>
  <application>
    <default-validators>
      <validator-id>jakarta.faces.Bean</validator-id>
    </default-validators>
  </application>
</faces-config>

A default validator may also be registered using the isDefault attribute on the @FacesValidator annotation on a Validator class, as specified in Requirements for scanning of classes for annotations.

The during application startup, the runtime must cause any default validators declared either in the application configuration resources, or via a @FacesValidator annotation with isDefault set to true to be added with a call to Application.addDefaultValidatorId(). This method is declared in Default Validator Ids.

Any configuration resource that declares a list of default validators overrides any list provided in a previously processed configuration resource. If an empty <default-validators/> element is found in a configuration resource, the list of default validators must be cleared.

In environments that include Bean Validation, the following additional actions must be taken at startup time. If the jakarta.faces.validator.DISABLE_DEFAULT_BEAN_VALIDATOR <context-param> exists and its value is true, the following step must be skipped:

  • The runtime must guarantee that the validator id jakarta.faces.Bean is included in the result from a call to Application.getDefaultValidatorInfo() (see Default Validator Ids), regardless of any configuration found in the application configuration resources or via the @FacesValidator annotation.

Validation Processing

During the Process Validations phase of the request processing lifecycle (as described in Process Validations), the Jakarta Faces implementation will ensure that the validate() method of each registered Validator, the method referenced by the validator property (if any), and the validate() method of the component itself, is called for each EditableValueHolder component in the component tree, regardless of the validity state of any of the components in the tree. The responsibilities of each validate() method include:

  • Perform the check for which this validator was registered.

  • If violation(s) of the correctness rules are found, create a FacesMessage instance describing the problem, and create a ValidatorException around it, and throw the ValidatorException. The EditableValueHolder on which this validation is being performed will catch this exception, set valid to false for that instance, and cause the message to be added to the FacesContext.

In addition, a validate() method may:

  • Examine or modify the state of any component in the component tree.

  • Add or remove components from the component tree.

  • Queue one or more events, from the same component or a different one, for processing during the current lifecycle phase.

The render-independent property required is a shorthand for the function of a “required” validator. If the value of this property is true, there is an entry in the request payload corresponding to this component, and the component has no value, the component is marked invalid and a message is added to the FacesContext instance. See Localized Application Messages for details on the message.

Standard Validator Implementations

Jakarta Faces defines a standard suite of Validator implementations that perform a variety of commonly required checks. In addition, component writers, application developers, and tool providers will often define additional Validator implementations that may be used to support component-type-specific or application-specific constraints. These implementations share the following common characteristics:

  • Standard Validators accept configuration information as either parameters to the constructor that creates a new instance of that Validator, or as JavaBeans component properties on the Validator implementation class.

  • To support internationalization, FacesMessage instances should be created. The message identifiers for such standard messages are also defined by manifest String constants in the implementation classes. It is the user’s responsibility to ensure the content of a FacesMessage instance is properly localized, and appropriate parameter substitution is performed, perhaps using java.text.MessageFormat.

  • See the javadocs for UIInput.validateValue() for further normative specification regarding validation.

  • Concrete Validator implementations must define a public static final String constant VALIDATOR_ID, whose value is the standard identifier under which the Jakarta Faces implementation must register this instance (see below).

Please see Localized Application Messages for the list of message identifiers.

The following standard Validator implementations (in the jakarta.faces.validator package) are provided:

  • DoubleRangeValidator —Checks the local value of a component, which must be of any numeric type, against specified maximum and/or minimum values. Standard identifier is “jakarta.faces.DoubleRange”.

  • LengthValidator —Checks the length (i.e. number of characters) of the local value of a component, which must be of type String, against maximum and/or minimum values. Standard identifier is “jakarta.faces.Length”.

  • LongRangeValidator —Checks the local value of a component, which must be of any numeric type convertible to long , against maximum and/or minimum values. Standard identifier is “jakarta.faces.LongRange”.

  • RegexValidator —Accepts a “pattern” attribute that is interpreted as a regular expression from the java.util.regex package. The local value of the component is checked fora match against this regular expression. Standard identifier is “jakarta.faces.RegularExpression”

  • BeanValidator - The implementation must ensure that this validator is only available when running in an environment in which JSR-303 Beans Validation is available. Please see the javadocs for BeanValidator.validate() for the specification. Standard identifier is “jakarta.faces.Bean”

  • RequiredValidator - Analogous to setting the required attribute to true on the EditableValueHolder. Enforces that the local value is not empty. Reuses the logic and error messages defined on UIInput. Standard identifier for this validator is "jakarta.faces.Required"

MethodExpressionValidator —Wraps a MethodExpression and interprets it as pointing to a method that performs validation. Any exception thrown when the expression is invoked is wrapped in a ValidatorException in similar fashion as the above validators.

Bean Validation Integration

If the implementation is running in a container environment that requires Jakarta Bean Validation, it must expose the bean validation as described in this specification.

As stated in the specification goals of Jakarta Bean Validation, validation often gets spread out across the application, from user interface components to persistent objects. Jakarta Bean Validation strives to avoid this duplication by defining a set of metadata that can be used to express validation constraints that are sharable by any layer of the application. Since its inception, Jakarta Faces has supported a “field level validation” approach. Rather than requiring the developer to define validators for each input component (i.e., EditableValueHolder), the BeanValidator can be automatically applied to all fields on a page so that the work of enforcing the constraints can be delegated to the Bean Validation provider.

Bean Validator Activation

If Bean Validation is present in the runtime environment, the system must ensure that the standard validator with validator-id jakarta.faces.Bean is added with a call to Application.addDefaultValidatorId(). See Standard Validator Implementations for the description of the standard BeanValidator, and <f:validateBean> for the Facelet tag that exposes this validator to the page author. This ensures Bean Validation will be called for every field in the application.

If Bean Validation is present, and the jakarta.faces.VALIDATE_EMPTY_FIELDS <context-param> is not explicitly set to false, Jakarta Faces will validate null and empty fields so that the @NotNull and @NotEmpty constraints from Bean Validation can be leveraged. The next section describes how the reference to the Bean Validation ValidatorFactory is obtained by that validator.

Obtaining a ValidatorFactory

The Bean Validation ValidatorFactory is the main entry point into Bean Validation and is responsible for creating Validator instances. A ValidatorFactory is retrieved using the following algorithm:

  • If the servlet context contains a ValidatorFactory instance under the attribute named jakarta.faces.validator.beanValidator.ValidatorFactory, this instance is used by Jakarta Faces to acquire Validator instances (specifically in the BeanValidator). This key should be defined in the constant named VALIDATOR_FACTORY_KEY on BeanValidator.

  • If the servlet context does not contain such an entry, Jakarta Faces looks for a Bean Validation provider in the classpath. If present, the standard Bean Validation bootstrap strategy is used. If not present, Bean Validation integration is disabled. If the BeanValidator is used an no ValidatorFactory can be retrieved, a FacesException is raised. The standard Bean Validation bootstrap procedure is shown here:

ValidatorFactory validatorFactory =
    Validation.buildDefaultValidatorFactory();

Once instantiated, the result can be stored in the servlet context attribute mentioned as a means of caching the result. If Jakarta Faces is running in a Jakarta EE environment, Jakarta Bean Validation will be available, as defined by the Jakarta EE specification, and thus activated in Jakarta Faces. The EE container will be responsible for making the ValidatorFactory available as an attribute in the ServletContext as mentioned above.

Class-Level Validation

Jakarta Faces conversion and validation as described in this chapter operates on the principle that all conversion and validation is performed before values are pushed into the model. This principle allows one to safely assume that if a value is pushed into the model, it is of the proper type and has been validated. This validation is done on a “field level” basis, as mentioned in Bean Validation Integration. This approach poses challenges for higher level validation that needs to take the value of several fields together into account to decide if they are valid or not. For example, consider the common case of a user account creation page with two fields for the password. The page can only be considered valid if both password fields are themselves individually valid based on the specified password constraints and also are both the same value. Jakarta Faces provides for this case by providing a facility for performing Class-Level Validation using Bean Validation. Please see the VDLDoc for the <f:validateWholeBean /> tag for the normative specification of this feature as well as a usage example showing the password validation scenario.

Localization of Bean Validation Messages

To ensure proper localization of the messages, Jakarta Faces should provide a custom BeanValidation MessageInterpolator resolving the Locale according to Jakarta Faces defaults and delegating to the default MessageInterpolator as defined in ValidationFactory.getMessageInterpolator(). A possible implementation is shown here:

public class FacesMessageInterpolator implements MessageInterpolator {
  private final MessageInterpolator delegate;

  public FacesMessageInterpolator(MessageInterpolator delegate) {
    this.delegate = delegate;
  }

  public String interpolate(String message,
      ConstraintDescriptor constraintDescriptor,Object value) {
    Locale locale = FacesContext.getCurrentInstance()
        .getViewRoot().getLocale();
    return this.delegate.interpolate(
        message, constraintDescriptor, value, locale);
  }

  public String interpolate(String message, ConstraintDescriptor
      constraintDescriptor, Object value, Locale locale) {
    return this.delegate.interpolate(
        message, constraintDescriptor, value, locale);
  }
}

Once a ValidatorFactory is obtained, as described in Obtaining a ValidatorFactory, Jakarta Faces receives a Validator instance by providing the custom message interpolator to the validator state.

//could be cached
MessageInterpolator facesMessageInterpolator = new FacesMessageInterpolator(
    validatorFactory.getMessageInterpolator() );

//...

Validator validator = validatorFactory
    .usingContext()
    .messageInterpolator(facesMessageInterpolator)
    .getValidator();

The local value is then passed to the Validator.validateValue() method to check for constraint violations. Since Bean Validation defines a strategy for localized message reporting, the BeanValidator does not need to concern itself with producing the validation message. Instead, the BeanValidator should accept the interpolated message returned from Bean Validation API, which is accessed via the method getInterpolatedMessage() on the ContraintFailure class, and use it as the replacement value for the first numbered placeholder for the key jakarta.faces.validator.BeanValidator.MESSAGE (i.e., {0}). To encourage use of the Bean Validation message facility, the default message format string for the BeanValidator message key must be a single placeholder, as shown here:

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

Putting the Bean Validation message resolution in full control of producing the displayed message is the recommended approach. However, to allow the developer to align the messages generated by the BeanValidator with existing Jakarta Faces validators, the developer may choose to override this message key in an application resource bundle and reference the component label, which replaces the second numbered placeholder (i.e., {1}).

jakarta.faces.validator.BeanValidator.MESSAGE={1}:{0}

This approach is useful if you are already using localized labels for your input components and are displaying the messages above the form, rather than adjacent to the input.

Composite User Interface Components

Non-normative Background

To aid implementors in providing a spec compliant runtime for composite components, this section provides a non-normative background to motivate the discussion of the composite component feature. The composite component feature enables developers to write real, reusable, Jakarta Faces UI components without any Java code or configuration XML.

What does it mean to be a Jakarta Faces User Interface component?

Jakarta Faces is a component based framework, and Jakarta Faces UI components are the main point of Jakarta Faces. But what is a Jakarta Faces UI component, really? Conceptually, a Jakarta Faces UI Component is a software artifact that represents a reusable, self contained piece of a user interface. A very narrow definition for “Jakarta Faces UI Component” is imposed at runtime. This definition can be summarized as

A Jakarta Faces UI Component is represented at runtime by an instance of a Java class that includes jakarta.faces.component.UIComponent as an ancestor in its inheritance hierarchy.

It is easy to write a class that adheres to this definition, but in practice, component authors need to do more than just this in order to get the most from Jakarta Faces and to conform to user’s expectations of what a Jakarta Faces UI Component is. For example, users expect a Jakarta Faces UI Component can do some or all of the following:

  • be exposed to the page-author via a markup tag with sensible attributes

  • emit events (such a ValueChangeEvent or ActionEvent)

  • allow attaching listeners

  • allow attaching a Converter and/or Validator(s)

  • render itself to the user-agent, with full support for styles, localization and accessibility

  • support delegated rendering to allow for client device independence

  • read values sent from the user-agent and correctly adapt them to the faces lifecycle

  • correctly handle saving and restoring its state across multiple requests from the user-agent

Another important dimension to consider regarding UI components is the context in which the developer interacts with the component. There are generally two such contexts.

  • In the context of a markup view, such as a Facelet view. In this context the developer interacts with the UI component using a markup element, setting attributes on that element, and nesting child elements within that component markup element.

  • In the context of code, such as a listener, a managed bean, or other programming language context. In this context, the developer is writing JavaCode that is either passed the UI component as an argument, or obtains a reference to the UI component in some other way.

How does one make a custom Jakarta Faces User Interface component?

To satisfy a user’s expectations for a Jakarta Faces UI component, the component author must adhere to one of the following best practices.

  • extend the custom component class from an existing subclass of UIComponent that most closely represents the meaning and behavior of the piece of the UI you are encapsulating in the component.

  • extend the custom component class directly from UIComponentBase and implement the appropriate “behavioral interface”(s) that most closely represents the meaning and behavior of the piece of the UI you are encapsulating in the component. See Component Behavioral Interfaces for more.

Note that the first best practice includes the second one “for free” since the stock UIComponent subclasses already implement the appropriate behavioral interfaces.

When following either best practice, the Jakarta Faces UI component developer must follow several steps to make the component available for use in markup pages or in code, including but not necessarily limited to

  • Make entries in a faces-config.xml file, linking the component class to its component-type, which enables the Application.createComponent() method to create instances of the component.

  • Make entries in a faces-config.xml file to declare a Renderer that provides client-device independence.

  • Provide a Facelet tag handler that allows the page author to build UIs that include the component, and to customize each instance of the component with listeners, properties and model associations. This includes making the association between the Renderer and the UIComponent.

  • Provide a Renderer that provides client device independency for the component

  • Make entries in a faces-config.xml file that links the Renderer and its Java class.

These steps are complex, yet the components one creates by following them can be very flexible and powerful. By making some simplifying assumptions, it is possible to allow the creation of components that are just as powerful but require far less complexity to develop. This is the whole point of composite components: to enable developers to write real, reusable, Jakarta Faces UI components without any Java code or configuration XML.

How does one make a composite component?

The composite component feature builds on two features in Jakarta Faces: resources (Resource Handling) and Facelets (Facelets and its use in Web Applications”). Briefly, a composite component is any Facelet markup file that resides inside of a resource library. For example, if a Facelet markup file named loginPanel.xhtml resides inside of a resource library called ezcomp, then page authors can use this component by declaring the xml namespace xmlns:ez="jakarta.faces.composite/ezcomp" and including the tag <ez:loginPanel /> in their pages. Naturally, it is possible for a composite component author to declare an alternate XML namespace for their composite components, but doing so is optional.

Any valid Facelet markup is valid for use inside of a composite component, including the templating features specified in Facelet Templating Tag Library. In addition, the tag library specified in Composite Component Tag Library must be used to declare the metadata for the composite component. Future versions of the Jakarta Faces specification may relax this requirement, but for now at least the <cc:interface> and <cc:implementation> sections are required when creating a composite component.

A simple composite component example

Create the page that uses the composite component, index.xhtml.

<!DOCTYPE html>
<html xmlns:f="jakarta.faces.core"
      xmlns:h="jakarta.faces.html"
      xmlns:ez="jakarta.faces.composite/ezcomp">
  <h:head>
    <title>A simple example of EZComp</title>
  </h:head>
  <h:body>
    <h:form>
      <ez:loginPanel id="loginPanel">
        <f:actionListener for="loginEvent"
                          binding="#{loginBacking.loginEventListener}" />
      </ez:loginPanel>
    </h:form>
  </h:body>
</html>

The only thing special about this page is the ez namespace declaration and the inclusion of the <ez:loginPanel /> tag on the page. The occurrence of the string “jakarta.faces.composite/” in a Facelet XML namespace declaration means that whatever follows that last “/” is taken to be the name of a resource library. For any usage of this namespace in the page, such as <ez:loginPanel />, a Facelet markup file with the corresponding name is loaded and taken to be the composite component, in this case the file loginPanel.xhtml. The implementation requirements for this and other Facelet features related to composite components are specified in Requirements specific to composite components.

Create the composite component markup page. In this case, loginPanel.xhtml resides in the ./resources/ezcomp directory relative to the index.xhtml file.

<ui:component xmlns:ui="jakarta.faces.facelets"
              xmlns:f="jakarta.faces.core"
              xmlns:h="jakarta.faces.html"
              xmlns:cc="jakarta.faces.composite">
  <cc:interface>
    <cc:actionSource name="loginEvent" />
  </cc:interface>
  <cc:implementation>
    <p>Username: <h:inputText id="usernameInput" /></p>
    <p>Password: <h:inputSecret id="passwordInput" /></p>
    <p><h:commandButton id="loginEvent" value="login"/></p>
  </cc:implementation>
</ui:component>

The <cc:interface> section declares the public interface that users of this component need to understand. In this case, the component declares that it contains an implementation of ActionSource (see ActionSource), and therefore anything one can do with an ActionSource in a Facelet markup page you one do with the composite component. (See Component Behavioral Interfaces for more on ActionSource and other behavioral interfaces). The <cc:implementation> section defines the implementation of this composite component.

Walk through of the run-time for the simple composite component example

This section gives a non-normative traversal of the composite component feature using the previous example as a guide. Please refer to the javadocs for the normative specification for each method mentioned below. Any text in italics is a term defined in Composite Component Terms.

  1. The user-agent requests the index.html from A simple composite component example. This page contains the xmlns:ez="jakarta.faces.composite/ezcomp" declaration and an occurrence of the <ez:loginPanel> tag. Because this page contains a usage of a composite component, it is called a using page for discussion.

    The runtime notices the use of an xml namespace beginning with “jakarta.faces.composite/”. Takes the substring of the namespace after the last “/”, exclusive, and looks for a resource library with the name “ezcomp” by calling ResourceHandler.libraryExists().

  2. The runtime encounters the <ez:loginPanel> component in the using page. This causes Application.createComponent(FacesContext, Resource) to be called. This method instantiates the top level component but does not populate it with children. Pay careful attention to the javadocs for this method. Depending on the circumstances, the top level component instance can come from a developer supplied Java Class, a Script, or an implementation specific java class. This method calls ViewDeclarationLanguage.getComponentMetadata(FacesContext, Resource), which obtains the composite component BeanInfo (and therefore also the composite component BeanDescriptor) that exposes the composite component metadata. The composite component metadata also includes any attached object targets exposed by the composite component author. One thing that Application.createComponent(FacesContext, Resource) does to the component before returning it is set the component’s renderer type to be jakarta.faces.Composite. This is important during rendering.

    Again, Application.createComponent(FacesContext, Resource) does not populate the top level component with children. Subsequent processing done as the runtime traverses the rest of the page takes care of that. One very important aspect of that subsequent processing is ensuring that all of the UIComponent children in the defining page are placed in a facet underneath the top level component. The name of that facet is given by the UIComponent.COMPOSITE_FACET_NAME constant.

  3. After the children of the composite component tag in the using page have been processed by the VDL implementation, the VDL implementation must call VDLUtils.retargetAttachedObjects(). This method examines the composite component metadata and retargets any attached objects from the using page to their approriate inner component targets.

  4. Because the renderer type of the composite component was set to jakarta.faces.Composite, the composite component renderer is invoked to render the composite component.

Composite Component Terms

The following terms are commonly used to describe the composite component feature.

Attached Object

Any artifact that can be attached to a UIComponent (composite or otherwise). Usually, this means a Converter, Validator, ActionListener, or ValueChangeListener.

Attached Object Target

Part of the composite component metadata that allows the composite component author to expose the semantics of an inner component to the using page author without exposing the rendering or implementation details of the inner component.

Composite Component

A tree of UIComponent instances, rooted at a top level component, that can be thought of and used as a single component in a view. The component hierarchy of this subtree is described in the composite component defining page.

Composite Component Author

The individual or role creating the composite component. This usually involves authoring the composite component defining page.

Composite Component BeanDescriptor

A constituent element of the composite component metadata. This version of the spec uses the JavaBeans API to expose the component metadata for the composite component. Future versions of the spec may use a different API to expose the component metadata.

Composite Component BeanInfo

The main element of the composite component metadata.

Composite Component Declaration

The section of markup within the composite component defining page that includes the <cc:interface> section and its children.

Composite Component Definition

The section of markup within the composite component defining page that includes the <cc:implementation> section and its children.

Composite Component Library

A resource library that contains a defining page for each composite component that the composite component author wishes to expose to the using page author.

Composite Component Metadata

Any data about the composite component. The normative specification for what must be in the composite component metadata is in the javadocs for ViewDeclarationLanguage.getComponentMetadata().

Composite Component Renderer

A new renderer in the HTML_BASIC render kit that knows how to render a composite component.

Composite Component Tag

The tag in the using page that references a composite component declared and defined in a defining page.

Defining page

The markup page, usually Facelets markup, that contains the composite component declaration and composite component definition.

Inner Component

Any UIComponent inside of the defining page or a page that is referenced from the defining page.

Top level component

The UIComponent instance in the tree that is the parent of all UIComponent instances within the defining page and any pages used by that defining page.

Using Page

The VDL page in which a composite component tag is used.

Using Page Author

The individual or role that creates pages that use the composite component.

Normative Requirements

This section contains the normative requirements for the composite component runtime, or pointers to other parts of the specification that articulate those requirements in the appropriate context.

Table 1. References to Composite Component Requirements in Context
Section Feature

Implicit Object ELResolver for Facelets and Programmatic Access

Ability for the composite component author to refer to the top level component from a Jakarta Expression Language expression, such as #{cc.children[3]}.

Composite Component Attributes ELResolver

Ability for the composite component author to refer to attributes declared on the composite component tag using EL expressions such as #{cc.attrs.usernameLabel}

Object Factories

Methods called by the VDL page to create a new instance of a top level component for eventual inclusion in the view

Requirements specific to composite components

Requirements of the Facelet implementation relating to Facelets.

Composite Component Tag Library

Tag handlers for the composite tag library

Composite Component Metadata

In the current version of the specification, only composite UIComponents must have component metadata. It is possible that future versions of the specification will broaden this requirement so that all UIComponents must have metadata.

This section describes the implementation of the composite component metadata that is returned from the method ViewDeclarationLanguage.getComponentMetadata(). This method is formally declared in ViewDeclarationLanguage.getComponentMetadata(), but for reference its signature is repeated here.

public BeanInfo getComponentMetadata(
    FacesContext context, Resource componentResource)

The specification requires that this method is called from Application.createComponent(FacesContext context, Resource componentResource). See the javadocs for that method for actions that must be taken based on the composite component metadata returned from getComponentMetadata().

The default implementation of this method must support authoring the component metadata using tags placed inside of a <cc:interface /> element found on a defining page. This element is specified in the Facelets taglibrary docs.

Composite component metadata currently consists of the following information:

  • The composite component BeanInfo, returned from this method.

  • The Resource from which the composite component was created.

  • The composite component BeanDescriptor.

    This BeanDescriptor must be returned when getBeanDescriptor() is called on the composite component BeanInfo.

    The composite component BeanDescriptor exposes the following information.

    • The “name” attributes of the <cc:interface/ > element is exposed using the corresponding method on the composite component BeanDescriptor. If ProjectStage is Development, The “displayName”, “shortDescription”, “expert”, “hidden”, and “preferred” attributes of the <cc:interface/ > element are exposed using the corresponding methods on the composite component BeanDescriptor. Any additional attributes on <cc:interface/ > are exposed as attributes accessible from the getValue() and attributeNames() methods on BeanDescriptor (inherited from FeatureDescriptor). The return type from getValue() must be a jakarta.el.ValueExpression for such attributes.

    • The list of exposed AttachedObjectTargets to which the page author can attach things such as listeners, converters, or validators.

      The VDL implementation must populate the composite component metadata with a List<AttachedObjectTarget> that includes all of the inner components exposed by the composite component author for use by the page author.

      This List must be exposed in the value set of the composite component BeanDescriptor under the key AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY.

      For example, if the defining page has

      <cc:interface>
        <cc:editableValueHolder name="username" />
        <cc:actionSource name="loginEvent" />
        <cc:actionSource name="allEvents"
                         targets="loginEvent cancelEvent" />
      </cc:interface>

      The list of attached object targets would consist of instances of implementations of the following interfaces from the package jakarta.faces.view.

      1. EditableValueHolderAttachedObjectTarget

      2. ActionSourceAttachedObjectTarget

      3. ActionSourceAttachedObjectTarget

      4. BehaviorHolderAttachedObjectTarget

    • A ValueExpression that evaluates to the component type of the composite component. By default this is "jakarta.faces.NamingContainer" but the composite component page author can change this, or provide a Java or script-based UIComponent implementation that is required to implement NamingContainer.

      This ValueExpression must be exposed in the value set of the composite component BeanDescriptor under the key UIComponent.COMPOSITE_COMPONENT_TYPE_KEY.

    • A Map<String, PropertyDescriptor> representing the facets declared by the composite component author for use by the page author.

      This Map must be exposed in the value set of the composite component BeanDescriptor under the key UIComponent.FACETS_KEY.

    • Any attributes declared by the composite component author using <cc:attribute/ > elements must be exposed in the array of PropertyDescriptors returned from getPropertyDescriptors() on the composite component BeanInfo.

      For each such attribute, for any String or boolean valued JavaBeans properties on the interface PropertyDescriptor (and its superinterfaces) that are also given as attributes on a <cc:attribute/ > element, those properties must be exposed as properties on the PropertyDescriptor for that markup element. Any additional attributes on <cc:attribute/ > are exposed as attributes accessible from the getValue() and attributeNames() methods on PropertyDescriptor. The return type from getValue() must be a ValueExpression with the exception of the getValue("type"). The return type from getValue("type") must be Class. If the value specified for the type attribute of <cc:attribute/> cannot be converted to an actual Class, a TagAttributeException must be thrown, including the Tag and TagAttribute instances in the constructor.

      The composite component BeanDescriptor must return a Collection<String> when its getValue() method is called with an argument equal to the value of the symbolic constant UIComponent.ATTRS_WITH_DECLARED_DEFAULT_VALUES. The Collection<String> must contain the names of any <cc:attribute> elements for which the default attribute was specified, or null if none of the attributes have been given a default value.

Component Behavior Model

This section describes the facilities for adding Behavior attached objects to Jakarta Faces components.

Overview

Jakarta Faces supports a mechanism for enhancing components with additional behaviors that are not explicitly defined by the component author.

At the root of the behavior model is he Behavior interface. This interface serves as a supertype for additional behavior contracts. The ClientBehavior interface extends the Behavior interface by providing a contract for defining reusable scripts that can be attached to any component that implements the ClientBehaviorHolder interface. The ClientBehaviorHolder interface defines the set of attach points, or "events", to which a ClientBehavior may be attached. For example, an "AlertBehavior" implementation might display a JavaScript alert when attached to a component and activated by the end user.

While client behaviors typically add client-side capabilities, they are not limited to client. Client behaviors can also participate in the Jakarta Faces request processing lifecycle. Jakarta Faces’s AjaxBehavior is a good example of such a cross-tier behavior. The AjaxBehavior both triggers an Ajax request from the client and also delivers AjaxBehaviorEvents to listeners on the server.

The standard HTML components provided by Jakarta Faces are all client behavior-ready. That is, all of the standard HTML components implement the ClientBehaviorHolder interface and allow client behaviors to be attached to well defined events. .

Behavior Interface

The Behavior interface is the root of the component behavior model. It defines a single method to enable generic behavior event delivery.

public void broadcast(BehaviorEvent event) throws AbortProcessingException

This method is called by UIComponent implementations to re-broadcast behavior events that were queued by by calling UIComponent.queueEvent.

BehaviorBase

The BehaviorBase abstract class implements the broadcast method from the Behavior interface. BehaviorBase also implements the PartialStateHolder interface (see PartialStateHolder). It also provides behavior event listener registration methods.

public void broadcast(BehaviorEvent event) throws AbortProcessingException

This method delivers the BehaviorEvent to listeners that were registered via addBehaviorListener.

The following methods are provided for add and removing BehaviorListeners.

protected void addBehaviorListener(BehaviorListener listener)
protected void removeBehaviorListener(BehaviorListener listener);

The Client Behavior Contract

The ClientBehavior interface extends the Behavior interface and lays the foundation on which behavior authors can define custom script producing behaviors. The logic for producing these scripts is defined in the getScript() method.

public String getScript(BehaviorContext behaviorContext)

This method returns a String that is an executable script that can be attached to a client side event handler. The BehaviorContext argument contains information that may be useful for getScript implementations.

In addition to client side functionality, client behaviors can also post back to the server and participate in the request processing lifecycle.

public void decode(FacesContext context,UIComponent component)

This method can perform request decoding and queue server side events.

public Set<ClientBehaviorHint> getHints()

This method provides information about the client behavior implementation that may be useful to components and renderers that interact with the client behavior.

Refer to the javadocs for these methods for more details.

ClientBehaviorHolder

Components that support client behaviors must implement the ClientBehaviorHolder interface. Refer to ClientBehaviorHolder for more details.

ClientBehaviorRenderer

Client behaviors may implement script generation and decoding in a client behavior class or delegate to a ClientBehaviorRenderer. Refer to ClientBehaviorRenderer for more specifics.

ClientBehaviorContext

The specification provides a ClientBehaviorContext that contains information that may be used at script rendering time. Specifically it includes:

  • FacesContext

  • UIComponent that the current behavior is attached to

  • The name of the event that the behavior is associated with

  • The identifier of the source - this may correspond to the identifier of the source of the behavior

  • A collection of parameters that submitting behaviors should include when posting back to the server

The ClientBehaviorContext is created with the use of this static method:

public static ClientBehaviorContext createClientBehaviorContext(
    FacesContext context,UIComponent component,
    String eventName, String sourceId,
    Collection<ClientBehaviorContext.Parameter> parameters)

This method must throw a NullPointerException if context, component or eventName is null.

ClientBehaviorHint

The ClientBehaviorHint enum is used to convey information about the client behavior implementation. Currently, only one hint is provided.

SUBMITTING

This hint indicates that a client behavior implementation posts back to the server.

ClientBehaviorBase

ClientBehaviorBase is an extension of BehaviorBase that implements the ClientBehavior interface. It It is a convenience class that contains default implementations for the methods in ClientBehavior plus additional methods:

public String getScript(BehaviorContext behaviorContext)

The default implementation calls getRenderer to retrieve the ClientBehaviorRenderer. If a ClientBehaviorRenderer is found, it is used to obtain the script. If no ClientBehaviorRenderer is found, this method returns null.

public void decode(FacesContext context,UIComponent component)

The default implementation calls getRenderer to retrieve the ClientBehaviorRenderer. If a ClientBehaviorRenderer is found, it is used to perform decoding. If no ClientBehaviorRenderer is found, no decoding is performed.

public Set<ClientBehaviorHint> getHints()

The default implementation returns an empty set

public String getRendererType();

This method identifies the ClientBehaviorRenderer type. By default, no ClientBehaviorRenderer type is provided. Subclasses should either override this method to return a valid type or override the getScript and decode methods if a ClientBehaviorRenderer is not available.

protected ClientBehaviorRenderer getRenderer(FacesContext context);

This method returns the ClientBehaviorRenderer instance that is associated with this ClientBehavior. It uses the renderer type returned from get RendererType() to look up the renderer on the RenderKit using RenderKit.getClientBehaviorRenderer.

Behavior Event / Listener Model

The behavior event / listener model is an extension of the Jakarta Faces event / listener model as described in Event and Listener Model. BehaviorHolder components are responsible for broadcasting BehaviorEvents to behaviors.

Event Classes

Behaviors can broadcast events in the same way that UIComponents can broadcast events. At the root of the behavior event hierarchy is BehaviorEvent that extends jakarta.faces.event.FacesEvent. All events that are broadcast by Jakarta Faces behaviors must extend the jakarta.faces.event.BehaviorEvent abstract base class. The parameter list for the constructor(s) of this event class must include a UIComponent, which identifies the component from which the event will be broadcast to interested listeners, and a Behavior which identifies the behavior associated with the component. The source component can be retrieved from the event object itself by calling getComponent and the behavior can be retrieved by calling getBehavior. Additional constructor parameters and/or properties on the event class can be used to relay additional information about the event.

In conformance to the naming patterns defined in the JavaBeans Specification, event classes typically have a class name that ends with Event. The following method is available to determine the Behavior for the event (in addition to the other methods inherited from jakarta.faces.event.FacesEvent):

public Behavior getBehavior()
Listener Classes

For each event type that may be emitted, a corresponding listener interface must be created, which extends the jakarta.faces.event.BehaviorListener interface. BehaviorListener extends from jakarta.faces.event.FacesListener. The method signature(s) defined by the listener interface must take a single parameter, an instance of the event class for which this listener is being created. A listener implementation class will implement one or more of these listener interfaces, along with the event handling method(s) specified by those interfaces. The event handling methods will be called during event broadcast, one per event.

In conformance to the naming patterns defined in the JavaBeans Specification, listener interfaces have a class name based on the class name of the event being listened to, but with the word Listener replacing the trailing Event of the event class name (thus, the listener for a FooEvent would be a FooListener). It is recommended that application event listener interfaces follow this naming pattern as well.

Listener Registration

BehaviorListener registration follows the same conventions as outlined in Listener Registration.

Ajax Behavior

AjaxBehavior

The specification defines a single concrete ClientBehavior implementation: jakarta.faces.component.behavior.AjaxBehavior. This class extends jakarta.faces.component.behavior.ClientBehaviorBase. The presence of this behavior on a component causes the rendering of JavaScript that will produce an Ajax request to the server using the JavaScript API outlined in Section “JavaScript API”. This behavior may also broadcast jakarta.faces.event.AjaxBehaviorEvents to registered jakarta.faces.event.AjaxBehaviorListener implementations. Refer to the javadocs for more details about AjaxBehavior. This behavior must define the behavior id “jakarta.faces.behavior.Ajax”. The renderer type must also be “jakarta.faces.behavior.Ajax”.

Ajax Behavior Event / Listener Model

Corresponding to the standard behavior event classes described in the previous section the specification supports an event listener model for broadcasting and handling AjaxBehavior events.

jakarta.faces.event.AjaxBehaviorEvent

This event type extends from jakarta.faces.event.BehaviorEvent and it is broadcast from an AjaxBehavior. This class follows the standard Jakarta Faces event / listener model, incorporating the usual methods as outlined in Event and Listener Model. This class is responsible for invoking the method implementation of jakarta.faces.event.AjaxBehaviorListener.processAjaxBehavior. Refer to the javadocs for more complete details about this class.

jakarta.faces.event.AjaxBehaviorListener

This listener type extends from jakarta.faces.event.BehaviorListener and it is invoked in response to AjaxBehaviorEvents.

public void processAjaxBehavior(AjaxBehaviorEvent event)

AjaxBehaviorListener implementations implement this method to provide server side functionality in response to AjaxBehavior Events. See the javadocs for more details about this class.

Adding Behavior To Components

Using the ClientBehaviorHolder interface (see ClientBehaviorHolder) ClientBehavior instances can be added to components. For ClientBehavior implementations that extend UIComponentBase, the minimal requirement is to override getEventNames() to return a non-empty collection of the event names exposed by the ClientBehaviorHolder. A optional default event name may be specified as well. For example:

Here’s an example code snippet from one of the Html components:

public class HtmlCommandButton extends
    jakarta.faces.component.UICommand implements ClientBehaviorHolder {
...
  private static final Collection<String> EVENT_NAMES =
      Collections.unmodifiableCollection(
          Arrays.asList("blur","change","click","action",...) );

  public Collection<String> getEventNames() {
    return EVENT_NAMES;
  }

  public String getDefaultEventName() {
    return "action";
  }
...

Users of the component will be able to attach ClientBehavior instances to any of the event names specified by the getEventNames() implementation by calling ClientBehaviorHolder.addBehavior(eventName, clientBehavior).

Behavior Registration

Jakarta Faces provides methods for registering Behavior implementations and these methods are similar to the methods used to register converters and validators. Refer to Object Factories for the specifics about these methods.

XML Registration

Jakarta Faces provides the usual faces-config.xml registration of custom component behavior implementations.

<behavior>
  <behavior-id>custom.behavior.Greet</behavior-id>
  <behavior-class>greet.GreetBehavior</behavior-class>
</behavior>
Registration By Annotation

Jakarta Faces provides the @FacesBehavior annotation for registering custom behavior implementations.

@FacesBehavior(value="custom.behavior.Greet")
public class GreetBehavior extends BehaviorBase implements Serializable {
...
}