Skip to content

Latest commit

 

History

History
295 lines (245 loc) · 11 KB

LifecycleManagement.adoc

File metadata and controls

295 lines (245 loc) · 11 KB

Lifecycle Management

In Request Processing Lifecycle, the required functionality of each phase of the request processing lifecycle was described. This chapter describes the standard APIs used by Jakarta Faces implementations to manage and execute the lifecycle. Each of these classes and interfaces is part of the jakarta.faces.lifecycle package.

Page authors, component writers, and application developers, in general, will not need to be aware of the lifecycle management APIs—they are primarily of interest to tool providers and Jakarta Faces implementors.

Lifecycle

Upon receipt of each Jakarta Faces-destined request to this web application, the Jakarta Faces implementation must acquire a reference to the Lifecycle instance for this web application, and call its execute() and render() methods to perform the request processing lifecycle. The Lifecycle instance invokes appropriate processing logic to implement the required functionality for each phase of the request processing lifecycle, as described in Standard Request Processing Lifecycle Phases.

public void execute(FacesContext context) throws FacesException;
public void render(FacesContext context) throws FacesException;

The execute() method performs phases up to, but not including, the Render Response phase. The render() method performs the Render Response phase. This division of responsibility makes it easy to support Jakarta Faces processing in a portlet-based environment.

As each phase is processed, registered PhaseListener instances are also notified. The general processing for each phase is as follows:

  • From the set of registered PhaseListener instances, select the relevant ones for the current phase, where “relevant” means that calling getPhaseId() on the PhaseListener instance returns the phase identifier of the current phase, or the special value PhaseId.ANY_PHASE.

  • Call the beforePhase() method of each relevant listener, in the order that the listeners were registered.

  • If no called listener called the FacesContext.renderResponse() or FacesContext.responseComplete() method, execute the functionality required for the current phase.

  • Call the afterPhase() method of each relevant listener, in the reverse of the order that the listeners were registered.

  • If the FacesContext.responseComplete() method has been called during the processing of the current request, or we have just completed the Render Response phase, perform no further phases of the request processing lifecycle.

  • If the FacesContext.renderResponse() method has been called during the processing of the current request, and we have not yet executed the Render Response phase of the request processing lifecycle, ensure that the next executed phase will be Render Response

public void addPhaseListener(PhaseListener listener);
public void removePhaseListener(PhaseListener listener);

These methods register or deregister a PhaseListener that wishes to be notified before and after the processing of each standard phase of the request processing lifecycle. Implementations should prevent duplicate PhaseListener registrations and log an exception if an attempt is made. The webapp author can declare a PhaseListener to be added using the phase-listener element of the application configuration resources file. Please see PhaseListener.

PhaseEvent

This class represents the beginning or ending of processing for a particular phase of the request processing lifecycle, for the request encapsulated by the FacesContext instance passed to our constructor.

public PhaseEvent(FacesContext context,
    PhaseId phaseId, Lifecycle lifecycle);

Construct a new PhaseEvent representing the execution of the specified phase of the request processing lifecycle, on the request encapsulated by the specified FacesContext instance. The Lifecycle instance must be the lifecycle used by the current FacesServlet that is processing the request. It will serve as the source of the java.util.EventObject from which PhaseEvent inherits.

public FacesContext getFacesContext();
public PhaseId getPhaseId();

Return the properties of this event instance. The specified FacesContext instance will also be returned if getSource() (inherited from the base EventObject class) is called.

PhaseListener

This interface must be implemented by objects that wish to be notified before and after the processing for a particular phase of the request processing lifecycle, on a particular request. Implementations of PhaseListener must be programmed in a thread-safe manner.

public PhaseId getPhaseId();

The PhaseListener instance indicates for which phase of the request processing lifecycle this listener wishes to be notified. If PhaseId.ANY_PHASE is returned, this listener will be notified for all standard phases of the request processing lifecycle.

public void beforePhase(PhaseEvent event);
public void afterPhase(PhaseEvent event);

The beforePhase() method is called before the standard processing for a particular phase is performed, while the afterPhase() method is called after the standard processing has been completed. The Jakarta Faces implementation must guarantee that, if beforePhase() has been called on a particular instance, then afterPhase() will also be called, regardless of any Exceptions that may have been thrown during the actual execution of the lifecycle phase. For example, let’s say there are three PhaseListeners attached to the lifecycle: A, B, and C, in that order. A.beforePhase() is called, and executes successfully. B.beforePhase() is called and throws an exception. Any exceptions thrown during the beforePhase() listeners must be caught and published to the ExceptionHandler, as described below. In this example, C.beforePhase() must not be called. Then the actual lifecycle phase executes. Any exceptions thrown during the execution of the actual phase, that reach the runtime code that implements the Jakarta Faces lifecycle phase, must be caught and and published to the ExceptionHandler, as described below. When the lifecycle phase exits, due to an exeception or normal termination, the afterPhase() listeners must be called in reverse order from the beforePhase() listeners in the following manner. C.afterPhase() must not be called, since C.beforePhase() was not called. B.afterPhase() must not be called, since B.beforePhase() did not execute successfully. A.afterPhase() must be called. Any exceptions thrown during the afterPhase() liseteners must be caught and published to the ExceptionHandler, as described below.

The previous paragraph detailed several cases where exceptions should be published to the Exception handler. The following action must be taken by the runtime to implement this requirement as well as an additional requirent to cause the ExceptionHandler to take action on the published Exception(s). The specification is shown in pseudocode. This code does not implement the before/after matching guarantees specified above and is only intended to describe the specification for publishing and handling ExceptionQueuedEvent instances that arise from exceptions being thrown during the execution of a lifecycle phase. Methods shown in thisTypeface() are not a part of the API and are just included for discussion.

FacesContext facesContext = FacesContext.getCurrentInstance();
Application app = facesContext.getApplication();
ExceptionHandler handler = facesContext.getExceptionHandler();

try {
  callBeforePhaseListeners();
} catch (Throwable thrownException) {
  jakarta.faces.event.ExceptionEventContext eventContext =
      new ExceptionEventContext(
          thrownException, null, facesContext.getPhaseId());
  eventContext.getAttributes()
      .put(EventContext.IN_BEFORE_PHASE, Boolean.TRUE);
  app.publishEvent(ExceptionQueuedEvent.class, eventContext);
}

try {
  doCurrentPhase();
} catch (Throwable thrownException) {
  jakarta.faces.event.ExceptionEventContext eventContext =
      new ExceptionEventContext(
          thrownException, null, facesContext.getPhaseId());
  app.publishEvent(ExceptionQueuedEvent.class, eventContext);
} finally {
  try {
    callAfterPhaseListeners();
  } catch (Throwable thrownException) {
    jakarta.faces.event.ExceptionEventContext eventContext =
        new ExceptionEventContext(
            thrownException, null, facesContext.getPhaseId());
    eventContext.getAttributes()
        .put(EventContext.IN_AFTER_PHASE, Boolean.TRUE);
    app.publishEvent(ExceptionQueuedEvent.class, eventContext);
  }
  handler.handle();
}

body text.

PhaseListener implementations may affect the remainder of the request processing lifecycle in several ways, including:

  • Calling renderResponse() on the FacesContext instance for the current request, which will cause control to transfer to the Render Response phase of the request processing lifecycle, once processing of the current phase is complete.

  • Calling responseComplete() on the FacesContext instance for the current request, which causes processing of the request processing lifecycle to terminate once the current phase is complete.

LifecycleFactory

A single instance of jakarta.faces.lifecycle.LifecycleFactory must be made available to each Jakarta Faces-based web application running in a servlet or portlet container. The factory instance can be acquired by Jakarta Faces implementations or by application code, by executing:

LifecycleFactory factory = (LifecycleFactory)
    FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);

The LifecycleFactory implementation class supports the following methods:

public void addLifecycle(String lifecycleId, Lifecycle lifecycle);

Register a new Lifecycle instance under the specified lifecycle identifier, and make it available via calls to the getLifecycle method for the remainder of the current web application’s lifetime.

public Lifecycle getLifecycle(String lifecycleId);

The LifecycleFactory implementation class provides this method to create (if necessary) and return a Lifecycle instance. All requests for the same lifecycle identifier from within the same web application will return the same Lifecycle instance, which must be programmed in a thread-safe manner.

Every Jakarta Faces implementation must provide a Lifecycle instance for a default lifecycle identifier that is designated by the String constant LifecycleFactory.DEFAULT_LIFECYCLE . For advanced uses, a Jakarta Faces implementation may support additional lifecycle instances, named with unique lifecycle identifiers.

public Iterator<String> getLifecycleIds();

This method returns an iterator over the set of lifecycle identifiers supported by this factory. This set must include the value specified by LifecycleFactory.DEFAULT_LIFECYCLE.