Look into current implementation
// Execute the phases up to but not including Render Response
public void execute(FacesContext context) throws FacesException {
if (context == null) {
throw new NullPointerException
(MessageUtils.getExceptionMessageString
(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "context"));
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("execute(" + context + ")");
}
for (int i = 1, len = phases.length -1 ; i < len; i++) { // Skip ANY_PHASE placeholder
if (context.getRenderResponse() ||
context.getResponseComplete()) {
break;
}
phases[i].doPhase(context, this, listeners.listIterator());
}
}
// Execute the Render Response phase
public void render(FacesContext context) throws FacesException {
if (context == null) {
throw new NullPointerException
(MessageUtils.getExceptionMessageString
(MessageUtils.NULL_PARAMETERS_ERROR_MESSAGE_ID, "context"));
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("render(" + context + ")");
}
if (!context.getResponseComplete()) {
response.doPhase(context, this, listeners.listIterator());
}
}
The RenderResponse phase will be particularly executed
response.doPhase(context, this, listeners.listIterator());
Now, we dig into function doPhase()
public void doPhase(FacesContext context,
Lifecycle lifecycle,
ListIterator<PhaseListener> listeners) {
context.setCurrentPhaseId(getId());
PhaseEvent event = null;
if (listeners.hasNext()) {
event = new PhaseEvent(context, this.getId(), lifecycle);
}
// start timing - include before and after phase processing
Timer timer = Timer.getInstance();
if (timer != null) {
timer.startTiming();
}
try {
handleBeforePhase(context, listeners, event);
if (!shouldSkip(context)) {
execute(context);
}
} catch (Throwable e) {
queueException(context, e);
} finally {
try {
handleAfterPhase(context, listeners, event);
} catch (Throwable e) {
queueException(context, e);
}
// stop timing
if (timer != null) {
timer.stopTiming();
timer.logResult(
"Execution time for phase (including any PhaseListeners) -> "
+ this.getId().toString());
}
context.getExceptionHandler().handle();
}
}
The order when a phase do the job is : beforePhase() [ handleBeforePhase(...)] -> execute() [execute(...)] -> afterPhase() [handleAfterPhase(...)]
What they did inside execute() in RenderResponse phase
public void execute(FacesContext facesContext) throws FacesException {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Entering RenderResponsePhase");
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("About to render view " +
facesContext.getViewRoot().getViewId());
}
// For requests intended to produce a partial response, we need prohibit
// writing any content outside of the view itself (f:view).
facesContext.getPartialViewContext();
try {
ViewHandler vh = facesContext.getApplication().getViewHandler();
ViewDeclarationLanguage vdl =
vh.getViewDeclarationLanguage(facesContext,
facesContext.getViewRoot().getViewId());
if (vdl != null) {
vdl.buildView(facesContext, facesContext.getViewRoot());
}
boolean viewIdsUnchanged;
do {
String beforePublishViewId = facesContext.getViewRoot().getViewId();
// the before render event on the view root is a special case to keep door open for navigation
// this must be called *after* PDL.buildView() and before VH.renderView()
facesContext.getApplication().publishEvent(facesContext,
PreRenderViewEvent.class,
facesContext.getViewRoot());
String afterPublishViewId = facesContext.getViewRoot().getViewId();
viewIdsUnchanged = beforePublishViewId == null && afterPublishViewId == null ||
(beforePublishViewId != null && afterPublishViewId != null) &&
beforePublishViewId.equals(afterPublishViewId);
if (facesContext.getResponseComplete()) {
return;
}
} while (!viewIdsUnchanged);
//render the view
vh.renderView(facesContext, facesContext.getViewRoot());
} catch (IOException e) {
throw new FacesException(e.getMessage(), e);
}
if (LOGGER.isLoggable(Level.FINEST)) {
LOGGER.log(Level.FINEST, "+=+=+=+=+=+= View structure printout for " + facesContext.getViewRoot().getViewId());
DebugUtil.printTree(facesContext.getViewRoot(), LOGGER, Level.FINEST);
}
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("Exiting RenderResponsePhase");
}
}
We will see SystemEvents
: PreRenderViewEvent will be executed.
facesContext.getApplication().publishEvent(facesContext, PreRenderViewEvent.class, facesContext.getViewRoot());
Extend
/**
* Handle <code>afterPhase</code> <code>PhaseListener</code> events.
* @param context the FacesContext for the current request
* @param listenersIterator a ListIterator for the PhaseListeners that need
* to be invoked
* @param event the event to pass to each of the invoked listeners
*/
protected void handleAfterPhase(FacesContext context,
ListIterator<PhaseListener> listenersIterator,
PhaseEvent event) {
try {
Flash flash = context.getExternalContext().getFlash();
flash.doPostPhaseActions(context);
} catch (UnsupportedOperationException uoe) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("ExternalContext.getFlash() throw UnsupportedOperationException -> Flash unavailable");
}
}
while (listenersIterator.hasPrevious()) {
PhaseListener listener = listenersIterator.previous();
if (this.getId().equals(listener.getPhaseId()) ||
PhaseId.ANY_PHASE.equals(listener.getPhaseId())) {
try {
listener.afterPhase(event);
} catch (Exception e) {
queueException(context,
e,
ExceptionQueuedEventContext.IN_AFTER_PHASE_KEY);
return;
}
}
}
}
/**
* Handle <code>beforePhase</code> <code>PhaseListener</code> events.
* @param context the FacesContext for the current request
* @param listenersIterator a ListIterator for the PhaseListeners that need
* to be invoked
* @param event the event to pass to each of the invoked listeners
*/
protected void handleBeforePhase(FacesContext context,
ListIterator<PhaseListener> listenersIterator,
PhaseEvent event) {
try {
Flash flash = context.getExternalContext().getFlash();
flash.doPrePhaseActions(context);
} catch (UnsupportedOperationException uoe) {
if (LOGGER.isLoggable(Level.FINE)) {
LOGGER.fine("ExternalContext.getFlash() throw UnsupportedOperationException -> Flash unavailable");
}
}
RequestStateManager.clearAttributesForPhase(context,
context.getCurrentPhaseId());
while (listenersIterator.hasNext()) {
PhaseListener listener = listenersIterator.next();
if (this.getId().equals(listener.getPhaseId()) ||
PhaseId.ANY_PHASE.equals(listener.getPhaseId())) {
try {
listener.beforePhase(event);
} catch (Exception e) {
queueException(context,
e,
ExceptionQueuedEventContext.IN_BEFORE_PHASE_KEY);
// move the iterator pointer back one
if (listenersIterator.hasPrevious()) {
listenersIterator.previous();
}
return;
}
}
}
}
SystemEvents will be execute in execution time
( not beforePhase, execute, not afterPhase ) of doPhase().
Two methods beforePhase listener.beforePhase(event);
and afterPhase listener.afterPhase(event);
will execute a PhaseListener.
All kind of SystemEvent:
System Event | Description |
---|---|
PreRenderComponentEvent | This event is published just before the rendering of the component. |
PostAddToViewEvent | This event is published just after the component is added to the JSF view. |
PreValidateEvent | This event is published just before the component is about to be validated. |
PostValidateEvent | This event is published just after the component is validated. |
PreDestroyViewMapEvent | This event is published just before the view scope map is about to be destroyed. |
PostConstructViewMapEvent | This event is published just after the view scope map is created. |
PreRenderViewEvent | This event is published just before the view (UIViewRoot) is about to be rendered. |
PostRestoreStateEvent | This event is published just after the component state is restored. |