/** * This method is called before the {@link PhaseId#INVOKE_APPLICATION} phase of the JSF lifecycle * is executed. The purpose of this timing is to handle the case when the user clicks on a {@link * UICommand} component (like h:commandButton or h:commandLink) that has been either * Auto-ajaxified by ICEfaces, or manually Ajaxified by the developer using code like the * following: * * <p><code><f:ajax execute="@form" render=" @form" /></code> * * <p>When this happens, we need to somehow remember the list of JavaScript and/or CSS resources * that are currently in the <head> section of the portal page. This is because a * navigation-rule might fire which could cause a new view to be rendered in the {@link * PhaseId#RENDER_RESPONSE} phase that is about to follow this {@link PhaseId#INVOKE_APPLICATION} * phase. The list of resources would be contained in the {@link HeadManagedBean} {@link * ViewScoped} instance that is managed by the JSF managed-bean facility. The list would have been * populated initially in the {@link HeadManagedBean} by the {@link HeadRender} during the initial * HTTP-GET of the portal page. The way we "remember" the list is by placing it into the JSF 2 * {@link Flash} scope. This scope is used because it is very short-lived and survives any * navigation-rules that might fire, thereby causing the rendering of a new JSF view. * * <p>The story is continued in the {@link #beforeRenderResponsePhase(PhaseEvent)} method below... */ protected void beforeInvokeApplicationPhase(PhaseEvent phaseEvent) { // Get the list of resourceIds that might be contained in the Flash scope. Note that they would // have been // placed into the Flash scope by this very same method, except during in the case below for the // RENDER_RESPONSE phase. FacesContext facesContext = phaseEvent.getFacesContext(); Flash flash = facesContext.getExternalContext().getFlash(); @SuppressWarnings("unchecked") Set<String> headResourceIdsFromFlash = (Set<String>) flash.get("HEAD_RESOURCE_IDS"); // Log the viewId so that it can be visually compared with the value that is to be logged after // the // INVOKE_APPLICATION phase completes. logger.debug("Before INVOKE_APPLICATION: viewId=[{0}]", facesContext.getViewRoot().getViewId()); // If the Flash scope does not yet contain a list of head resourceIds, then the scope needs to // be populated // with a list so that the {@link #beforeRenderResponsePhase(PhaseEvent)} method below can // retrieve it. if (headResourceIdsFromFlash == null) { HeadManagedBean headManagedBean = HeadManagedBean.getInstance(facesContext); // Note that in the case where a portlet RESOURCE_PHASE was invoked with a "portlet:resource" // type of URL, // there will be no HeadManagedBean available. if (headManagedBean != null) { flash.put("HEAD_RESOURCE_IDS", headManagedBean.getHeadResourceIds()); } } }
/** * This method is called before the {@link PhaseId#RENDER_RESPONSE} phase of the JSF lifecycle is * executed. The purpose of this timing is to pick up where the {@link * #beforeInvokeApplicationPhase(PhaseEvent)} method left off. It might be the case that a * navigation-rule has fired and a NEW JSF view has been loaded up after the INVOKE_APPLICATION * phase completed. If this is the case, then the list of head resourceIds in the {@link * HeadManagedBean} needs to be repopulated from the list found in the Flash scope. */ protected void beforeRenderResponsePhase(PhaseEvent phaseEvent) { FacesContext facesContext = phaseEvent.getFacesContext(); Flash flash = facesContext.getExternalContext().getFlash(); String viewId = facesContext.getViewRoot().getViewId(); @SuppressWarnings("unchecked") Set<String> headResourceIdsFromFlash = (Set<String>) flash.get("HEAD_RESOURCE_IDS"); if (headResourceIdsFromFlash != null) { HeadManagedBean headManagedBean = HeadManagedBean.getInstance(facesContext); Set<String> managedBeanResourceIds = headManagedBean.getHeadResourceIds(); for (String resourceIdFromFlash : headResourceIdsFromFlash) { if (!managedBeanResourceIds.contains(resourceIdFromFlash)) { managedBeanResourceIds.add(resourceIdFromFlash); logger.debug( "Added resourceId=[{0}] from the Flash scope to the list of resourceIds in the HeadManagedBean for viewId=[{1}]", resourceIdFromFlash, viewId); } } } }