myfaces-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ssilv...@apache.org
Subject svn commit: r391470 - in /myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle: LifecycleImpl.java PhaseListenerManager.java
Date Wed, 05 Apr 2006 03:14:27 GMT
Author: ssilvert
Date: Tue Apr  4 20:14:25 2006
New Revision: 391470

URL: http://svn.apache.org/viewcvs?rev=391470&view=rev
Log:
Fix PhaseListener processing as per MYFACES-1205

Added:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/PhaseListenerManager.java
Modified:
    myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java

Modified: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java
URL: http://svn.apache.org/viewcvs/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java?rev=391470&r1=391469&r2=391470&view=diff
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java
(original)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/LifecycleImpl.java
Tue Apr  4 20:14:25 2006
@@ -61,27 +61,29 @@
     public void execute(FacesContext facesContext)
         throws FacesException
     {
-        if (restoreView(facesContext))
+        PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, facesContext,
getPhaseListeners());
+        
+        if (restoreView(facesContext, phaseListenerMgr))
         {
             return;
         }
 
-        if (applyRequestValues(facesContext))
+        if (applyRequestValues(facesContext, phaseListenerMgr))
         {
             return;
         }
 
-        if (processValidations(facesContext))
+        if (processValidations(facesContext, phaseListenerMgr))
         {
             return;
         }
 
-        if (updateModelValues(facesContext))
+        if (updateModelValues(facesContext, phaseListenerMgr))
         {
             return;
         }
 
-        invokeApplication(facesContext);
+        invokeApplication(facesContext, phaseListenerMgr);
     }
 
 
@@ -91,91 +93,93 @@
      * Restore View (JSF.2.2.1)
      * @return true, if immediate rendering should occur
      */
-    private boolean restoreView(FacesContext facesContext)
+    private boolean restoreView(FacesContext facesContext, PhaseListenerManager phaseListenerMgr)
         throws FacesException
     {
     		boolean skipFurtherProcessing = false;
         if (log.isTraceEnabled()) log.trace("entering restoreView in " + LifecycleImpl.class.getName());
 
-        informPhaseListenersBefore(facesContext, PhaseId.RESTORE_VIEW);
+        try {
+            phaseListenerMgr.informPhaseListenersBefore(PhaseId.RESTORE_VIEW);
 
-        if(isResponseComplete(facesContext, "restoreView", true))
-        {
-        		// have to skips this phase
-        		return true;
-        }
-        if (shouldRenderResponse(facesContext, "restoreView", true)) 
-        {
-			skipFurtherProcessing = true;
-		}
-
-        // Derive view identifier
-        String viewId = deriveViewId(facesContext);
+            if(isResponseComplete(facesContext, "restoreView", true))
+            {
+                            // have to skips this phase
+                            return true;
+            }
+            if (shouldRenderResponse(facesContext, "restoreView", true)) 
+            {
+                            skipFurtherProcessing = true;
+                    }
 
-        if(viewId == null)
-        {
-            ExternalContext externalContext = facesContext.getExternalContext();
+            // Derive view identifier
+            String viewId = deriveViewId(facesContext);
 
-            if(!externalContext.getRequestServletPath().endsWith("/"))
+            if(viewId == null)
             {
-                try
-                {
-                    externalContext.redirect(externalContext.getRequestServletPath()+"/");
-                    facesContext.responseComplete();
-                    return true;
-                }
-                catch (IOException e)
+                ExternalContext externalContext = facesContext.getExternalContext();
+
+                if(!externalContext.getRequestServletPath().endsWith("/"))
                 {
-                    throw new FacesException("redirect failed",e);
+                    try
+                    {
+                        externalContext.redirect(externalContext.getRequestServletPath()+"/");
+                        facesContext.responseComplete();
+                        return true;
+                    }
+                    catch (IOException e)
+                    {
+                        throw new FacesException("redirect failed",e);
+                    }
                 }
             }
-        }
 
-        Application application = facesContext.getApplication();
-        ViewHandler viewHandler = application.getViewHandler();
+            Application application = facesContext.getApplication();
+            ViewHandler viewHandler = application.getViewHandler();
 
-        //boolean viewCreated = false;
-        UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewId);
-        if (viewRoot == null)
-        {
-            viewRoot = viewHandler.createView(facesContext, viewId);
-            viewRoot.setViewId(viewId);
-            facesContext.renderResponse();
-            //viewCreated = true;
-        }
-
-        facesContext.setViewRoot(viewRoot);
-
-        /* This section has been disabled because it causes some bug.
-         * Be careful if you need to re-enable it.
-         * Furthermore, for an unknown reason, it seems that by default
-         * it is executed (i.e. log.isTraceEnabled() is true).
-         * Bug example :
-         * This traceView causes DebugUtil.printComponent to print all the attributes
-         * of the view components.
-         * And if you have a data table within an aliasBean, this causes the data table
-         * to initialize it's value attribute while the alias isn't set.
-         * So, the value initializes with an UIData.EMPTY_DATA_MODEL, and not with the aliased
one.
-         * But as it's initialized, it will not try to get the value from the ValueBinding
next
-         * time it needs to.
-         * I expect this to cause more similar bugs.
-         * TODO : Completely remove or be SURE by default it's not executed, and it has no
more side-effects.
+            //boolean viewCreated = false;
+            UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewId);
+            if (viewRoot == null)
+            {
+                viewRoot = viewHandler.createView(facesContext, viewId);
+                viewRoot.setViewId(viewId);
+                facesContext.renderResponse();
+                //viewCreated = true;
+            }
 
-        if (log.isTraceEnabled())
-        {
-            //Note: DebugUtils Logger must also be in trace level
-            DebugUtils.traceView(viewCreated ? "Newly created view" : "Restored view");
-        }*/
+            facesContext.setViewRoot(viewRoot);
 
-        if (facesContext.getExternalContext().getRequestParameterMap().isEmpty())
-        {
-            //no POST or query parameters --> set render response flag
-            facesContext.renderResponse();
-        }
+            /* This section has been disabled because it causes some bug.
+             * Be careful if you need to re-enable it.
+             * Furthermore, for an unknown reason, it seems that by default
+             * it is executed (i.e. log.isTraceEnabled() is true).
+             * Bug example :
+             * This traceView causes DebugUtil.printComponent to print all the attributes
+             * of the view components.
+             * And if you have a data table within an aliasBean, this causes the data table
+             * to initialize it's value attribute while the alias isn't set.
+             * So, the value initializes with an UIData.EMPTY_DATA_MODEL, and not with the
aliased one.
+             * But as it's initialized, it will not try to get the value from the ValueBinding
next
+             * time it needs to.
+             * I expect this to cause more similar bugs.
+             * TODO : Completely remove or be SURE by default it's not executed, and it has
no more side-effects.
 
-        RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(facesContext, viewRoot);
+            if (log.isTraceEnabled())
+            {
+                //Note: DebugUtils Logger must also be in trace level
+                DebugUtils.traceView(viewCreated ? "Newly created view" : "Restored view");
+            }*/
+
+            if (facesContext.getExternalContext().getRequestParameterMap().isEmpty())
+            {
+                //no POST or query parameters --> set render response flag
+                facesContext.renderResponse();
+            }
 
-        informPhaseListenersAfter(facesContext, PhaseId.RESTORE_VIEW);
+            RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(facesContext,
viewRoot);
+        } finally {
+            phaseListenerMgr.informPhaseListenersAfter(PhaseId.RESTORE_VIEW);
+        }
 
         if (isResponseComplete(facesContext, "restoreView", false)
 				|| shouldRenderResponse(facesContext, "restoreView", false))
@@ -193,27 +197,29 @@
      * Apply Request Values (JSF.2.2.2)
      * @return true, if response is complete
      */
-    private boolean applyRequestValues(FacesContext facesContext)
+    private boolean applyRequestValues(FacesContext facesContext, PhaseListenerManager phaseListenerMgr)
         throws FacesException
     {
     		boolean skipFurtherProcessing = false;
         if (log.isTraceEnabled()) log.trace("entering applyRequestValues in " + LifecycleImpl.class.getName());
 
-        informPhaseListenersBefore(facesContext, PhaseId.APPLY_REQUEST_VALUES);
+        try {
+            phaseListenerMgr.informPhaseListenersBefore(PhaseId.APPLY_REQUEST_VALUES);
 
-        if(isResponseComplete(facesContext, "applyRequestValues", true))
-        {
-        		// have to return right away
-        		return true;
-        }
-        if(shouldRenderResponse(facesContext, "applyRequestValues", true))
-        {
-        		skipFurtherProcessing = true;
-        }
-
-        facesContext.getViewRoot().processDecodes(facesContext);
+            if(isResponseComplete(facesContext, "applyRequestValues", true))
+            {
+                            // have to return right away
+                            return true;
+            }
+            if(shouldRenderResponse(facesContext, "applyRequestValues", true))
+            {
+                            skipFurtherProcessing = true;
+            }
 
-        informPhaseListenersAfter(facesContext, PhaseId.APPLY_REQUEST_VALUES);
+            facesContext.getViewRoot().processDecodes(facesContext);
+        } finally {
+            phaseListenerMgr.informPhaseListenersAfter(PhaseId.APPLY_REQUEST_VALUES);
+        }
 
 
         if (isResponseComplete(facesContext, "applyRequestValues", false)
@@ -234,26 +240,29 @@
      * Process Validations (JSF.2.2.3)
      * @return true, if response is complete
      */
-    private boolean processValidations(FacesContext facesContext) throws FacesException
+    private boolean processValidations(FacesContext facesContext, PhaseListenerManager phaseListenerMgr)
+        throws FacesException
     {
         boolean skipFurtherProcessing = false;
         if (log.isTraceEnabled()) log.trace("entering processValidations in " + LifecycleImpl.class.getName());
 
-        informPhaseListenersBefore(facesContext, PhaseId.PROCESS_VALIDATIONS);
+        try {
+            phaseListenerMgr.informPhaseListenersBefore(PhaseId.PROCESS_VALIDATIONS);
 
-        if(isResponseComplete(facesContext, "processValidations", true))
-        {
-        		// have to return right away
-        		return true;
-        }
-        if(shouldRenderResponse(facesContext, "processValidations", true))
-        {
-        		skipFurtherProcessing = true;
-        }
-
-        facesContext.getViewRoot().processValidators(facesContext);
+            if(isResponseComplete(facesContext, "processValidations", true))
+            {
+                            // have to return right away
+                            return true;
+            }
+            if(shouldRenderResponse(facesContext, "processValidations", true))
+            {
+                            skipFurtherProcessing = true;
+            }
 
-        informPhaseListenersAfter(facesContext, PhaseId.PROCESS_VALIDATIONS);
+            facesContext.getViewRoot().processValidators(facesContext);
+        } finally {
+            phaseListenerMgr.informPhaseListenersAfter(PhaseId.PROCESS_VALIDATIONS);
+        }
 
 		if (isResponseComplete(facesContext, "processValidations", false)
 				|| shouldRenderResponse(facesContext, "processValidations", false))
@@ -271,26 +280,29 @@
      * Update Model Values (JSF.2.2.4)
      * @return true, if response is complete
      */
-    private boolean updateModelValues(FacesContext facesContext) throws FacesException
+    private boolean updateModelValues(FacesContext facesContext, PhaseListenerManager phaseListenerMgr)
+        throws FacesException
     {
 	    boolean skipFurtherProcessing = false;
         if (log.isTraceEnabled()) log.trace("entering updateModelValues in " + LifecycleImpl.class.getName());
 
-        informPhaseListenersBefore(facesContext, PhaseId.UPDATE_MODEL_VALUES);
+        try {
+            phaseListenerMgr.informPhaseListenersBefore(PhaseId.UPDATE_MODEL_VALUES);
 
-        if(isResponseComplete(facesContext, "updateModelValues", true))
-        {
-        		// have to return right away
-        		return true;
-        }
-        if(shouldRenderResponse(facesContext, "updateModelValues", true))
-        {
-        		skipFurtherProcessing = true;
-        }
-
-        facesContext.getViewRoot().processUpdates(facesContext);
+            if(isResponseComplete(facesContext, "updateModelValues", true))
+            {
+                            // have to return right away
+                            return true;
+            }
+            if(shouldRenderResponse(facesContext, "updateModelValues", true))
+            {
+                            skipFurtherProcessing = true;
+            }
 
-        informPhaseListenersAfter(facesContext, PhaseId.UPDATE_MODEL_VALUES);
+            facesContext.getViewRoot().processUpdates(facesContext);
+        } finally {
+            phaseListenerMgr.informPhaseListenersAfter(PhaseId.UPDATE_MODEL_VALUES);
+        }
 
 		if (isResponseComplete(facesContext, "updateModelValues", false)
 				|| shouldRenderResponse(facesContext, "updateModelValues", false))
@@ -309,27 +321,29 @@
      * Invoke Application (JSF.2.2.5)
      * @return true, if response is complete
      */
-    private boolean invokeApplication(FacesContext facesContext)
+    private boolean invokeApplication(FacesContext facesContext, PhaseListenerManager phaseListenerMgr)
         throws FacesException
     {
 	    boolean skipFurtherProcessing = false;
         if (log.isTraceEnabled()) log.trace("entering invokeApplication in " + LifecycleImpl.class.getName());
 
-        informPhaseListenersBefore(facesContext, PhaseId.INVOKE_APPLICATION);
+        try {
+            phaseListenerMgr.informPhaseListenersBefore(PhaseId.INVOKE_APPLICATION);
 
-        if(isResponseComplete(facesContext, "invokeApplication", true))
-        {
-        		// have to return right away
-        		return true;
-        }
-        if(shouldRenderResponse(facesContext, "invokeApplication", true))
-        {
-        		skipFurtherProcessing = true;
-        }
-
-        facesContext.getViewRoot().processApplication(facesContext);
+            if(isResponseComplete(facesContext, "invokeApplication", true))
+            {
+                            // have to return right away
+                            return true;
+            }
+            if(shouldRenderResponse(facesContext, "invokeApplication", true))
+            {
+                            skipFurtherProcessing = true;
+            }
 
-        informPhaseListenersAfter(facesContext, PhaseId.INVOKE_APPLICATION);
+            facesContext.getViewRoot().processApplication(facesContext);
+        } finally {
+            phaseListenerMgr.informPhaseListenersAfter(PhaseId.INVOKE_APPLICATION);
+        }
 
 		if (isResponseComplete(facesContext, "invokeApplication", false)
 				|| shouldRenderResponse(facesContext, "invokeApplication", false))
@@ -353,25 +367,30 @@
         }
         if (log.isTraceEnabled()) log.trace("entering renderResponse in " + LifecycleImpl.class.getName());
 
-        informPhaseListenersBefore(facesContext, PhaseId.RENDER_RESPONSE);
-        // also possible that one of the listeners completed the response
-        if(isResponseComplete(facesContext, "render", true))
-        {
-        		return;
+        PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, facesContext,
getPhaseListeners());
+     
+        try {
+            phaseListenerMgr.informPhaseListenersBefore(PhaseId.RENDER_RESPONSE);
+            // also possible that one of the listeners completed the response
+            if(isResponseComplete(facesContext, "render", true))
+            {
+                            return;
+            }
+            Application application = facesContext.getApplication();
+            ViewHandler viewHandler = application.getViewHandler();
+
+            try
+            {
+                viewHandler.renderView(facesContext, facesContext.getViewRoot());
+            }
+            catch (IOException e)
+            {
+                throw new FacesException(e.getMessage(), e);
+            }
+        } finally {
+            phaseListenerMgr.informPhaseListenersAfter(PhaseId.RENDER_RESPONSE);
         }
-        Application application = facesContext.getApplication();
-        ViewHandler viewHandler = application.getViewHandler();
         
-        try
-        {
-            viewHandler.renderView(facesContext, facesContext.getViewRoot());
-        }
-        catch (IOException e)
-        {
-            throw new FacesException(e.getMessage(), e);
-        }
-
-        informPhaseListenersAfter(facesContext, PhaseId.RENDER_RESPONSE);
         if (log.isTraceEnabled())
         {
             //Note: DebugUtils Logger must also be in trace level
@@ -490,36 +509,6 @@
     }
 
 
-    private void informPhaseListenersBefore(FacesContext facesContext, PhaseId phaseId)
-    {
-        PhaseListener[] phaseListeners = getPhaseListeners();
-        for (int i = 0; i < phaseListeners.length; i++)
-        {
-            PhaseListener phaseListener = phaseListeners[i];
-            int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
-            if (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal() ||
-                listenerPhaseId == phaseId.getOrdinal())
-            {
-                phaseListener.beforePhase(new PhaseEvent(facesContext, phaseId, this));
-            }
-        }
-
-    }
-
-    private void informPhaseListenersAfter(FacesContext facesContext, PhaseId phaseId)
-    {
-        PhaseListener[] phaseListeners = getPhaseListeners();
-        for (int i = 0; i < phaseListeners.length; i++)
-        {
-            PhaseListener phaseListener = phaseListeners[i];
-            int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
-            if (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal() ||
-                listenerPhaseId == phaseId.getOrdinal())
-            {
-                phaseListener.afterPhase(new PhaseEvent(facesContext, phaseId, this));
-            }
-        }
-
-    }
+    
 
 }

Added: myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/PhaseListenerManager.java
URL: http://svn.apache.org/viewcvs/myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/PhaseListenerManager.java?rev=391470&view=auto
==============================================================================
--- myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/PhaseListenerManager.java
(added)
+++ myfaces/core/trunk/impl/src/main/java/org/apache/myfaces/lifecycle/PhaseListenerManager.java
Tue Apr  4 20:14:25 2006
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.myfaces.lifecycle;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.faces.context.FacesContext;
+import javax.faces.event.PhaseEvent;
+import javax.faces.event.PhaseId;
+import javax.faces.event.PhaseListener;
+import javax.faces.lifecycle.Lifecycle;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * This class encapsulates the logic used to call PhaseListeners.  It was 
+ * needed because of issue 9 of the JSF 1.2 spec.  See section 11.3 for more
+ * details.
+ *
+ * @author Stan Silvert
+ */
+class PhaseListenerManager {
+    
+    private static final Log log = LogFactory.getLog(PhaseListenerManager.class);
+    
+    private Lifecycle lifecycle;
+    private FacesContext facesContext;
+    private PhaseListener[] phaseListeners;
+    
+    // Tracks success in the beforePhase.  Listeners that throw an exception
+    // in beforePhase or were never called because a previous listener threw
+    // an exception should not have its afterPhase called
+    private Map<PhaseId, boolean[]> listenerSuccessMap = 
+                new HashMap<PhaseId, boolean[]>();
+    
+    /** Creates a new instance of PhaseListenerManager */
+    PhaseListenerManager(Lifecycle lifecycle, FacesContext facesContext, PhaseListener[]
phaseListeners) {
+        this.lifecycle = lifecycle;
+        this.facesContext = facesContext;
+        this.phaseListeners = phaseListeners;
+    }
+    
+    private boolean isListenerForThisPhase(PhaseListener phaseListener, PhaseId phaseId)
{
+        int listenerPhaseId = phaseListener.getPhaseId().getOrdinal();
+        return (listenerPhaseId == PhaseId.ANY_PHASE.getOrdinal() ||
+                listenerPhaseId == phaseId.getOrdinal());
+    }
+    
+    void informPhaseListenersBefore(PhaseId phaseId) {
+        boolean[] beforePhaseSuccess = new boolean[phaseListeners.length];
+        listenerSuccessMap.put(phaseId, beforePhaseSuccess);
+        
+        for (int i = 0; i < phaseListeners.length; i++) {
+            PhaseListener phaseListener = phaseListeners[i];
+            if (isListenerForThisPhase(phaseListener, phaseId)) {
+                try {
+                    phaseListener.beforePhase(new PhaseEvent(facesContext, phaseId, lifecycle));
+                    beforePhaseSuccess[i] = true;
+                } catch (Exception e) {
+                    beforePhaseSuccess[i] = false; // redundant - for clarity
+                    log.error("Exception in PhaseListener " + phaseId.toString() + " beforePhase.",
e);
+                    return;
+                }
+            }
+        }
+    }
+
+    void informPhaseListenersAfter(PhaseId phaseId) {
+        boolean[] beforePhaseSuccess = listenerSuccessMap.get(phaseId);
+        
+        for (int i = phaseListeners.length - 1; i >= 0; i--)  {
+            PhaseListener phaseListener = phaseListeners[i];
+            if (isListenerForThisPhase(phaseListener, phaseId) 
+                && beforePhaseSuccess[i]) {
+                try {
+                    phaseListener.afterPhase(new PhaseEvent(facesContext, phaseId, lifecycle));
+                } catch (Exception e) {
+                    log.error("Exception in PhaseListener " + phaseId.toString() + " afterPhase",
e);
+                }
+            }
+        }
+
+    }
+}



Mime
View raw message