You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by mf...@apache.org on 2009/01/30 00:14:10 UTC

svn commit: r739077 - in /myfaces/portlet-bridge/core/trunk_2.0.x: api/src/main/java/javax/portlet/faces/ impl/src/main/java/org/apache/myfaces/portlet/faces/application/ impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/ impl/src/main/resourc...

Author: mfreedman
Date: Thu Jan 29 23:14:10 2009
New Revision: 739077

URL: http://svn.apache.org/viewvc?rev=739077&view=rev
Log:
Fixes PORTLETBRIDGE-61, PORTLETBRIDGE-60, PORTLETBRIDGE-59, and PORTLETBRIDGE-58.

PB-61:  restoring from cached view has been moved from ViewHandler to before we run the lifecycle.

PB-60: create/init portlet now done in a synchronized block.

PB-59: Various face-config.xml(s) updated to provide a schemaLocation for the JSF schema so validation can occur.

PB-58:  Changed impl to recreate Lifecycle object per request vs. using a shared single copy stored as a private data member.

Modified:
    myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
    myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/resources/META-INF/faces-config.xml

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java?rev=739077&r1=739076&r2=739077&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/GenericFacesPortlet.java Thu Jan 29 23:14:10 2009
@@ -122,6 +122,7 @@
   private Class<? extends Bridge> mFacesBridgeClass = null;
   private Bridge mFacesBridge = null;
   private HashMap<String, String> mDefaultViewIdMap = null;
+  private Object mLock = new Object();  // used to synchronize on when initializing the bridge.
 
   /**
    * Initialize generic faces portlet from portlet.xml
@@ -654,9 +655,17 @@
     {
       try
       {
-        mFacesBridge = mFacesBridgeClass.newInstance();
-        mFacesBridge.init(getPortletConfig());
-      } catch (Exception e)
+        // ensure we only ever create/init one bridge per portlet
+        synchronized(mLock)
+        {
+          if (mFacesBridge == null)
+          {
+            mFacesBridge = mFacesBridgeClass.newInstance();
+            mFacesBridge.init(getPortletConfig());
+          }
+        }
+      }
+      catch (Exception e)
       {
         throw new PortletException("doBridgeDisptach:  error instantiating the bridge class", e);
       }

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java?rev=739077&r1=739076&r2=739077&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/application/PortletViewHandlerImpl.java Thu Jan 29 23:14:10 2009
@@ -218,36 +218,6 @@
   
   
   @Override
-  public UIViewRoot restoreView(FacesContext context, String viewId)
-  {
-    /* Because Faces doesn't support saving a view following an action, the bridge
-     * caches the view and restores the view from the cache for the first render.
-     * Once a render occurs the view is saved/restored from the Faces StateManager. 
-     * The view(root) is cached in the bridge request scope which means that
-     * by the time we are asked to restore here, the view(root) is a request
-     * attribute.  Logic below merely checks to see if this attribute exists. 
-     * If it does it removes the attribute from the request scope ensuring it
-     * won't be used in the future and then returns it.  Otherwise it delegates to
-     * the regular Faces restoration process.
-     */
-      
-    Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
-    UIViewRoot viewRoot = (UIViewRoot) requestMap.get(BridgeImpl.FACES_VIEWROOT);
-    if (viewRoot != null)
-    {
-      // remove from current Request Scope
-      requestMap.remove(BridgeImpl.FACES_VIEWROOT);
-    }
-    else
-    {
-      viewRoot = super.restoreView(context, viewId);
-    }
-    
-    return viewRoot;
-  }
-
-
-  @Override
   public void renderView(FacesContext context, UIViewRoot viewToRender) throws IOException,
                                                                        FacesException
   {

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java?rev=739077&r1=739076&r2=739077&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/BridgeImpl.java Thu Jan 29 23:14:10 2009
@@ -48,6 +48,7 @@
 import javax.faces.application.ApplicationFactory;
 import javax.faces.application.FacesMessage;
 import javax.faces.application.ViewHandler;
+import javax.faces.component.UIViewRoot;
 import javax.faces.context.ExternalContext;
 import javax.faces.context.FacesContext;
 import javax.faces.context.FacesContextFactory;
@@ -507,18 +508,18 @@
 
     FacesContext context = null;
     String scopeId = request.getParameter(REQUEST_SCOPE_ID_RENDER_PARAM);
-      if (scopeId != null)
+    if (scopeId != null)
+    {
+      // Its possible we didn't detect the mode change but its the wrong scope
+      // as the scope is encoded with the mode -- confirm its right
+      StringBuffer sb = new StringBuffer(10);
+      String modeCheck = sb.append(":").append(request.getPortletMode().toString()).append(":").toString();
+      if (scopeId.indexOf(modeCheck) < 0 )
       {
-        // Its possible we didn't detect the mode change but its the wrong scope
-        // as the scope is encoded with the mode -- confirm its right
-        StringBuffer sb = new StringBuffer(10);
-        String modeCheck = sb.append(":").append(request.getPortletMode().toString()).append(":").toString();
-        if (scopeId.indexOf(modeCheck) < 0 )
-        {
-          // scope is for a different mode
-          scopeId = null;
-        }
+        // scope is for a different mode
+        scopeId = null;
       }
+    }
     boolean restoredScope = false;
     
     restoredScope = restoreBridgeRequestScopeData(request, scopeId);
@@ -527,6 +528,13 @@
     {
       // Get the FacesContext instance for this request
       context = getFacesContext(request, response, getLifecycle(), null);
+      
+      if (restoredScope)
+      {
+        // only restores if a render has never occurred in this scope
+        // once a render occurs, the view is saved/restored via Faces
+        restoreFacesView(context, scopeId);        
+      }
    
       // in case a prior scope was managed temporarily on the session -- remove it
       request.getPortletSession().removeAttribute(BRIDGE_PACKAGE_PREFIX + REQUEST_SCOPE_ID_RENDER_PARAM);
@@ -735,6 +743,11 @@
         // VIEW_STATE
         // parameter -- always attempt a restore
         extRequest = restoreActionParams(context);
+        
+        // only restores if first render after action
+        // afterwards not restored from Bridge request scope
+        // rather its saved/restored by Faces.
+        restoreFacesView(context, scopeId);
       }
 
       // Ensure the ContentType is set before rendering
@@ -854,49 +867,36 @@
     // will create a new Tree instead of restoring one -- the semantics
     // one should get if the Bridge can't access its requestScope.
 
-    // if the requestScope restored the ViewRoot then this must be
-    // the first render after the action -- hence the tree isn't yet
-    // stored/managed by Faces -- we can merely render it
-    
-    // ViewRoot should always = null in the resourec case
-    if (context.getViewRoot() == null)
-    {
-      // add self as PhaseListener to restore Messages and in the case of 
-      // the render phase, prevent excuting beyond restoreView
-      if (BridgeUtil.getPortletRequestPhase() ==  Bridge.PortletPhase.RENDER_PHASE
-          && !mappedPublicParams)
-         // if public params mapped then run whole lifecycle so values are pushed into view
-      {
-        lifecycle.addPhaseListener(this);
-      }
+    // add self as PhaseListener to restore Messages and in the case of 
+    // the render phase, prevent excuting beyond restoreView
+    if (BridgeUtil.getPortletRequestPhase() ==  Bridge.PortletPhase.RENDER_PHASE
+        && !mappedPublicParams)
+        // if public params mapped then run whole lifecycle so values are pushed into view
+    {
+      lifecycle.addPhaseListener(this);
+    }
       
-      try
-      {
-        lifecycle.execute(context);
-      }
-      catch (Exception e)
-      {
-        // When exception occurs remove stored scope so don't
-        // get stuck replaying the error when/if user refreshes
-        if (scopeId != null)
-        {
-          removeRequestScopes(scopeId);
-        }
-      }
-      finally
+    try
+    {
+      lifecycle.execute(context);
+    }
+    catch (Exception e)
+    {
+      // When exception occurs remove stored scope so don't
+      // get stuck replaying the error when/if user refreshes
+      if (scopeId != null)
       {
-        if (BridgeUtil.getPortletRequestPhase() ==  Bridge.PortletPhase.RENDER_PHASE)
-        {
-          lifecycle.removePhaseListener(this);
-        }
+        removeRequestScopes(scopeId);
       }
     }
-    else
+    finally
     {
-      throw new BridgeException("Shouldn't get here -- disabled cached restore.");
+      if (BridgeUtil.getPortletRequestPhase() ==  Bridge.PortletPhase.RENDER_PHASE)
+      {
+        lifecycle.removePhaseListener(this);
+      }
     }
 
-
     // check here to see if a redirect occurred -- if so rerun doFacesRequest
     // for this new view
     QueryString redirectParams = (QueryString) context.getExternalContext()
@@ -946,6 +946,7 @@
       {
         if (BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RESOURCE_PHASE)
         {
+          saveFacesMessageState(context);
           saveBridgeRequestScopeData(context, scopeId, preExistingAttributes);
         }
         updateViewInfo(context, scopeId);
@@ -1403,6 +1404,22 @@
     Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
     requestMap.put(FACES_VIEWROOT, context.getViewRoot());
   }
+  
+  private void restoreFacesView(FacesContext context, String scopeId)
+  {
+    Map<String, Object> requestMap = context.getExternalContext().getRequestMap();
+    UIViewRoot viewRoot = (UIViewRoot) requestMap.get(FACES_VIEWROOT);
+    if (viewRoot != null)
+    {
+      context.setViewRoot(viewRoot);
+      // remove from current Request Scope and the saved Bridge Request
+      // Scope
+      requestMap.remove(FACES_VIEWROOT);
+      removeFromBridgeRequestScopeData(context, scopeId, FACES_VIEWROOT);
+    }
+    
+    // Messages get restored in a phase listener
+  }  
 
   private void saveActionParams(FacesContext context)
   {

Modified: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/resources/META-INF/faces-config.xml
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/resources/META-INF/faces-config.xml?rev=739077&r1=739076&r2=739077&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/resources/META-INF/faces-config.xml (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/resources/META-INF/faces-config.xml Thu Jan 29 23:14:10 2009
@@ -1,32 +1,35 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-    Licensed to the Apache Software Foundation (ASF) under one
-    or more contributor license agreements.  See the NOTICE file
-    distributed with this work for additional information
-    regarding copyright ownership.  The ASF licenses this file
-    to you 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.	   
--->
-<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
-    xmlns:bridge="http://www.apache.org/myfaces/xml/ns/bridge/bridge-extension">
-    <application>
-        <view-handler>org.apache.myfaces.portlet.faces.application.PortletViewHandlerImpl</view-handler>
-        <state-manager>org.apache.myfaces.portlet.faces.application.PortletStateManagerImpl</state-manager>
-        <el-resolver>org.apache.myfaces.portlet.faces.el.PortletELResolver</el-resolver>
-        <application-extension>
-          <bridge:excluded-attributes>
-            <bridge:excluded-attribute>com.sun.faces.*</bridge:excluded-attribute>
-          </bridge:excluded-attributes>       
-        </application-extension>
-    </application>
-</faces-config>
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you 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.	   
+-->
+<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
+    xmlns:bridge="http://www.apache.org/myfaces/xml/ns/bridge/bridge-extension"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
+    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
+
+    <application>
+        <view-handler>org.apache.myfaces.portlet.faces.application.PortletViewHandlerImpl</view-handler>
+        <state-manager>org.apache.myfaces.portlet.faces.application.PortletStateManagerImpl</state-manager>
+        <el-resolver>org.apache.myfaces.portlet.faces.el.PortletELResolver</el-resolver>
+        <application-extension>
+          <bridge:excluded-attributes>
+            <bridge:excluded-attribute>com.sun.faces.*</bridge:excluded-attribute>
+          </bridge:excluded-attributes>       
+        </application-extension>
+    </application>
+</faces-config>