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 2008/12/11 23:24:19 UTC
svn commit: r725844 - in /myfaces/portlet-bridge/core/trunk_2.0.x:
api/src/main/java/javax/portlet/faces/
api/src/main/java/javax/portlet/faces/event/
impl/src/main/java/org/apache/myfaces/portlet/faces/bridge/
impl/src/main/java/org/apache/myfaces/por...
Author: mfreedman
Date: Thu Dec 11 14:24:19 2008
New Revision: 725844
URL: http://svn.apache.org/viewvc?rev=725844&view=rev
Log:
More updates to implement 1st Portlet 2.0 draft.
Added:
myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgePublicRenderParameterHandler.java
myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/event/EventNavigationResult.java
Removed:
myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/event/PublicRenderParametersChangedEvent.java
Modified:
myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/Bridge.java
myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeEventHandler.java
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/bridge/BridgeImpl.java
myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
Modified: myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/Bridge.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/Bridge.java?rev=725844&r1=725843&r2=725844&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/Bridge.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/Bridge.java Thu Dec 11 14:24:19 2008
@@ -12,6 +12,8 @@
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
import javax.portlet.PortletConfig;
import javax.portlet.PortletException;
import javax.portlet.RenderRequest;
@@ -434,6 +436,23 @@
ActionResponse response) throws BridgeDefaultViewNotSpecifiedException,
BridgeUninitializedException,
BridgeException;
+
+ /**
+ * Called by the portlet when it wants the bridge to process an event request.
+ *
+ * @param request
+ * the request object.
+ * @param response
+ * the response object.
+ * @throws BridgeUninitializedException
+ * thrown if the bridge is not initialized.
+ * @throws BridgeException
+ * all other internal exceptions are converted to a BridgeException.
+ */
+ public void doFacesRequest(EventRequest request,
+ EventResponse response) throws BridgeUninitializedException,
+ BridgeException;
+
/**
* Called by the portlet when it wants the bridge to process a render request.
Modified: myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeEventHandler.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeEventHandler.java?rev=725844&r1=725843&r2=725844&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeEventHandler.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgeEventHandler.java Thu Dec 11 14:24:19 2008
@@ -12,13 +12,51 @@
import javax.faces.context.FacesContext;
import javax.portlet.Event;
+import javax.portlet.faces.event.EventNavigationResult;
/**
- *
+ * The <code>BridgeEventHandler</code> interface defines the class the bridge relies
+ * on to process portlet events. Because portlet events have arbitrary payloads
+ * the bridge provides no automated mappings to managed beans. Instead, the bridge
+ * calls the <code>handleEvent</code> method on the <code>BridgeEventHandler</code>
+ * instance passed to it (via a <code>PortletContext</code> attrbiute at init time.
+ * This method is expected to update any models based on the event's payload
+ * and then to perform any needed application recomputation to ensure a
+ * consistent state. The method is called after the <code>FacesContext</code>
+ * has been established and the <code>Lifecycle</code> has restored the view.<p>
+ * A view navigation can be affected by returning a non-null <code>EventNavigationResult</code>.
+ * Such an object will contain two <code>String</code> values: a fromAction and
+ * an outcome. These correspond to the from action and outcomes in Faces
+ * navigation rules. Using this information the bridge affects the navigation
+ * by calling the Faces <code>NavigationHandler</code>.
*/
public interface BridgeEventHandler
{
- public void handleEvent(FacesContext context, Event event);
+ /**
+ * Called by the bridge when it needs to process a portlet event.<p>
+ *
+ * Because portlet events have arbitrary payloads
+ * the bridge provides no automated mappings to managed beans. Instead, the bridge
+ * calls the <code>handleEvent</code> method on the <code>BridgeEventHandler</code>
+ * instance passed to it (via a <code>PortletContext</code> attrbiute at init time.
+ * This method is expected to update any models based on the event's payload
+ * and then to perform any needed application recomputation to ensure a
+ * consistent state. The method is called after the <code>FacesContext</code>
+ * has been established and the <code>Lifecycle</code> has restored the view.<p>
+ * A view navigation can be affected by returning a non-null <code>EventNavigationResult</code>.
+ * Such an object will contain two <code>String</code> values: a fromAction and
+ * an outcome. These correspond to the from action and outcomes in Faces
+ * navigation rules. Using this information the bridge affects the navigation
+ * by calling the Faces <code>NavigationHandler</code>.
+ *
+ * @param context
+ * current FacesContext. A Lifecycle has been acquired and the current view restored.
+ * @param event
+ * the portlet event. Other portlet information (request/response) is accessed via the ExternalContext.
+ * @return an object containing the fromAction and outcome of any navigation that resulted from this event.
+ * If the event doesn't cause a navigation, return null.
+ */
+ public EventNavigationResult handleEvent(FacesContext context, Event event);
}
Added: myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgePublicRenderParameterHandler.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgePublicRenderParameterHandler.java?rev=725844&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgePublicRenderParameterHandler.java (added)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/BridgePublicRenderParameterHandler.java Thu Dec 11 14:24:19 2008
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+package javax.portlet.faces;
+
+import javax.faces.context.FacesContext;
+import javax.portlet.Event;
+
+
+ /**
+ * The <code>BridgePublicRenderParameterHandler</code> interface defines the class the bridge relies
+ * on to post process portlet public render parameters. The handler provides the
+ * portlet a means for resynching application state following any model updates
+ * that resulted from the bridge pushing changed public render parameter values
+ * based on declarative mappings. After the bridge pushes such values the bridge
+ * calls the handler if it has been configured during bridge <code>init()</code>.
+ * Though the FacesContext has been acquired before the portlet is called to
+ * process these updates, the Lifecycle has not been acquired or run. Because
+ * of this is is no current active view. Unlike events, one can't navigate
+ * based on a public render parameter change.
+ */
+
+public interface BridgePublicRenderParameterHandler
+{
+ /**
+ * Called by the bridge after pushing incoming public render parameter
+ * values into mapped managed beans. Only called if there is at least
+ * one public render parameter in the incoming request whose value is
+ * different (updates) the underlying bean. This give the portlet an
+ * opportunity to perform further computations based on these changes to
+ * resynchronize its application state.
+ *
+ * @param context
+ * current FacesContext. A Lifecycle has been acquired and the current view restored.
+ */
+ public void processUpdates(FacesContext context);
+}
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=725844&r1=725843&r2=725844&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 Dec 11 14:24:19 2008
@@ -176,6 +176,13 @@
getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
Bridge.BRIDGE_EVENT_HANDLER, eventHandler);
}
+
+ BridgePublicRenderParameterHandler prpHandler = getBridgePublicRenderParameterHandler();
+ if (prpHandler != null)
+ {
+ getPortletContext().setAttribute(Bridge.BRIDGE_PACKAGE_PREFIX + getPortletName() + "." +
+ Bridge.BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER, prpHandler);
+ }
// Don't instanciate/initialize the bridge yet. Do it on first use
}
@@ -293,6 +300,45 @@
return null;
}
+
+ /**
+ * Returns an instance of a BridgePublicRenderParameterHandler used to post
+ * process public render parameter changes that the bridge
+ * has pushed into mapped models.
+ * This default implementation looks for a portlet initParameter that
+ * names the class used to instantiate the handler.
+ * @return an instance of BridgeRenderParameterHandler or null if there is none.
+ */
+ public BridgePublicRenderParameterHandler getBridgePublicRenderParameterHandler()
+ {
+ String prpHandlerClass =
+ getPortletConfig().getInitParameter(Bridge.BRIDGE_PACKAGE_PREFIX + Bridge.BRIDGE_PUBLIC_RENDER_PARAMETER_HANDLER);
+ if (prpHandlerClass != null)
+ {
+ try
+ {
+ ClassLoader loader = Thread.currentThread().getContextClassLoader();
+ Class<? extends BridgePublicRenderParameterHandler> c =
+ (Class<? extends BridgePublicRenderParameterHandler>) loader.loadClass(prpHandlerClass);
+ return c.newInstance();
+ } catch (ClassNotFoundException cnfe)
+ {
+ // Do nothing and fall through to null check
+ // TODO: log something
+ } catch (InstantiationException ie)
+ {
+ // Do nothing and fall through to null check
+ // TODO: log something
+ } catch (Exception e)
+ {
+ // Do nothing and fall through to null check
+ // TODO: log something
+ }
+ }
+
+ return null;
+ }
+
/**
Added: myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/event/EventNavigationResult.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/event/EventNavigationResult.java?rev=725844&view=auto
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/event/EventNavigationResult.java (added)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/api/src/main/java/javax/portlet/faces/event/EventNavigationResult.java Thu Dec 11 14:24:19 2008
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+package javax.portlet.faces.event;
+
+
+/**
+ * An <code>EventNavigationResult</code> is the type of object that can
+ * be returned from a <code>BrdigeEventHandler.handleEvent</code> call.
+ * When it is returned (non-null) it conveys the Faces navigation information
+ * to the bridge that it needs to utilize the Faces <code>NavigationHandler</code>
+ * to evaluate the navigation according to the configured rules. The
+ * <code>fromAction</code> corresponds to the <code>fromAction</code> string
+ * in the faces-config.xml navigation rule. The <code>outcome</code>
+ * corresponds to the <code>outcome</code> string in the navigation rule.
+ */
+
+public class EventNavigationResult extends Object
+{
+ private String mFromAction;
+ private String mOutcome;
+
+ /**
+ * Null constructor
+ */
+ public EventNavigationResult()
+ {
+
+ }
+
+ /**
+ * Constructor which sets the object to the desired fromAction and outcome
+ *
+ * @param action
+ * desired fromAction
+ * @param outcome
+ * desired outcome
+ */
+ public EventNavigationResult(String action, String outcome)
+ {
+ mFromAction = action;
+ mOutcome = outcome;
+ }
+
+ /**
+ * Gets the fromAction stored in this object. The <code>fromAction</code>
+ * corresponds to the <code>fromAction</code> string in the faces-config.xml
+ * navigation rule.
+ *
+ * @return <code>String</code> containing the fromAction
+ */
+ public String getFromAction()
+ {
+ return mFromAction;
+ }
+
+ /**
+ * Sets the fromAction for this object. The <code>fromAction</code>
+ * corresponds to the <code>fromAction</code> string in the faces-config.xml
+ * navigation rule.
+ *
+ * @param action
+ * new fromAction
+ */
+ public void setFromAction(String action)
+ {
+ mFromAction = action;
+ }
+
+ /**
+ * Gets the outcome stored in this object. The <code>outcome</code>
+ * corresponds to the <code>outcome</code> string in the faces-config.xml
+ * navigation rule.
+ *
+ * @return <code>String</code> containing the fromAction
+ */
+ public String getOutcome()
+ {
+ return mOutcome;
+ }
+
+ /**
+ * Sets the fromAction for this object. The <code>fromAction</code>
+ * corresponds to the <code>fromAction</code> string in the faces-config.xml
+ * navigation rule.
+ *
+ * @param outcome
+ * new outcome
+ */
+ public void setOutcome(String outcome)
+ {
+ mOutcome = outcome;
+ }
+
+}
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=725844&r1=725843&r2=725844&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 Dec 11 14:24:19 2008
@@ -61,6 +61,8 @@
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.ClientDataRequest;
+import javax.portlet.EventRequest;
+import javax.portlet.EventResponse;
import javax.portlet.MimeResponse;
import javax.portlet.PortalContext;
import javax.portlet.PortletConfig;
@@ -87,7 +89,7 @@
import javax.portlet.faces.annotation.BridgeRequestScopeAttributeAdded;
import javax.portlet.faces.annotation.ExcludeFromManagedRequestScope;
-import javax.portlet.faces.event.PublicRenderParametersChangedEvent;
+import javax.portlet.faces.event.EventNavigationResult;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
@@ -267,6 +269,9 @@
// instanceof which can fail if a portlet container uses a single class
// to implement both the action and render request/response objects
request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, Bridge.PortletPhase.ACTION_PHASE);
+
+ // Set the PortletName for use throughout this request to read portlet specific context attrs
+ request.setAttribute(PORTLET_NAME_ATTRIBUTE, mPortletConfig.getPortletName());
// Set the FacesServletMapping attribute so the ExternalContext can
// pick it up and use it to reverse map viewIds to paths
@@ -431,6 +436,192 @@
}
}
+
+ public void doFacesRequest(EventRequest request, EventResponse response)
+ throws BridgeException,
+ BridgeDefaultViewNotSpecifiedException,
+ BridgeUninitializedException,
+ NullPointerException
+ {
+ if (!mInitialized)
+ throw new BridgeUninitializedException();
+ else if (request == null || response == null)
+ throw new NullPointerException("request or response parameter is null");
+
+ // Do nothing if we don't have a BriegeEventHandler
+ if (mEventHandler == null)
+ {
+ // make sure the render parameters are carried forward into the next request
+ response.setRenderParameters(request);
+ // TODO: maybe log something here?
+ return;
+ }
+
+ // First check to see whether this is a non-JSF request
+ if (request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER) != null)
+ {
+ throw new BridgeNotAFacesRequestException("NonFaces target = "
+ + request.getParameter(Bridge.NONFACES_TARGET_PATH_PARAMETER));
+ }
+
+ // must wait until after init to get at the session
+ // since view mode mapping must always exist -- check it
+ StringBuffer keyBuf = new StringBuffer(30);
+ String key = keyBuf.append(Bridge.VIEWID_HISTORY).append(".view").toString();
+ if (request.getPortletSession().getAttribute(key) == null)
+ {
+ initViewHistoryDefaults(request.getPortletSession(), mDefaultViewIdMap);
+ }
+
+ // Set the Portlet lifecycle phase as a request attribute so its
+ // available to Faces extensions -- allowing that code to NOT rely on
+ // instanceof which can fail if a portlet container uses a single class
+ // to implement both the action and render request/response objects
+ request.setAttribute(Bridge.PORTLET_LIFECYCLE_PHASE, Bridge.PortletPhase.EVENT_PHASE);
+
+ // Set the PortletName for use throughout this request to read portlet specific context attrs
+ request.setAttribute(PORTLET_NAME_ATTRIBUTE, mPortletConfig.getPortletName());
+
+ // Set the FacesServletMapping attribute so the ExternalContext can
+ // pick it up and use it to reverse map viewIds to paths
+ if (mFacesMappings != null)
+ {
+ request.setAttribute(PortletExternalContextImpl.FACES_MAPPING_ATTRIBUTE, mFacesMappings);
+ }
+
+ // cache names of existing request attributes so can exclude them
+ // from being saved in the bridge's request scope. Note: this is done
+ // before
+ // acquiring the FacesContext because its possible (though unlikely)
+ // the application has inserted itself in this process and sets up
+ // needed request attributes.
+ List<String> preExistingAttributes = getRequestAttributes(request);
+ // place on the request for use here and in the servletRequestAttributeListener
+ if (preExistingAttributes != null)
+ {
+ request.setAttribute(PREEXISTING_ATTRIBUTE_NAMES, preExistingAttributes);
+ }
+
+ // Make sure that at a minimum the current render parameters are carried forward
+ response.setRenderParameters(request);
+
+ FacesContext context = null;
+ String scopeId = request.getParameter(REQUEST_SCOPE_ID_RENDER_PARAM);
+ 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 )
+ {
+ // scope is for a different mode
+ scopeId = null;
+ }
+ }
+ boolean restoredScope = false;
+
+ restoredScope = restoreBridgeRequestScopeData(request, scopeId);
+
+ try
+ {
+ // Get the FacesContext instance for this request
+ context = getFacesContext(request, response, getLifecycle(), null);
+
+ // in case a prior scope was managed temporarily on the session -- remove it
+ request.getPortletSession().removeAttribute(BRIDGE_PACKAGE_PREFIX + REQUEST_SCOPE_ID_RENDER_PARAM);
+
+ // process public render parameters -- note pass in the portlet request as this
+ // exposes the PPR where the one in the ExternalContext doesn't
+ processIncomingPublicRenderParameters(context, request);
+
+ // add self as PhaseListener to prevent action phase from executing (after restoreView)
+ Lifecycle lifecycle = getLifecycle();
+ lifecycle.addPhaseListener(this);
+
+ // For actions we only execute the lifecycle phase
+ lifecycle.execute(context);
+
+ // call the eventhandler to process
+ EventNavigationResult result = mEventHandler.handleEvent(context, request.getEvent());
+
+ if (result != null)
+ {
+ context.getApplication().getNavigationHandler().handleNavigation(context, result.getFromAction(), result.getOutcome());
+ }
+
+ finalizeActionResponse(context);
+
+ // Process any Public Render parameter changes
+ processOutgoingPublicRenderParameters(context, request, response);
+
+
+ // Now check to see if we need to save the scope
+ // We don't save scope if the finalizeActionResponse detected
+ // a mode change
+ Boolean noScope = (Boolean) request.getAttribute(PortletExternalContextImpl.NO_SCOPE);
+ if (noScope == null || noScope.equals(Boolean.FALSE))
+ {
+
+ // If event occurred before an action we don't have acope yet
+ if (scopeId == null)
+ {
+ scopeId = initBridgeRequestScope(request, response);
+ }
+
+ // Before preserving the request scope data in the bridge's
+ // request scope,
+ // put the Faces view into request scope. This is done because
+ // JSF 1.2 manages the tree save state opaquely exclusively in
+ // the render phase -- I.e. there is no JSF 1.2 way of having
+ // the
+ // bridge manually save and restore the view
+ saveFacesView(context);
+
+ // Because the portlet model doesn't execute its render phase
+ // within the same request scope but Faces does (assumes this),
+ // preserve the request scope data and the Faces view tree at
+ // RequestScope.
+ saveBridgeRequestScopeData(context, scopeId, preExistingAttributes);
+ }
+
+ }
+ catch (Exception e)
+ {
+ mPortletConfig.getPortletContext().log("Exception thrown in doFacesRequest:action", e);
+ if (!(e instanceof BridgeException))
+ {
+ Throwable rootCause = e.getCause();
+ throw new BridgeException(e.getMessage(), rootCause);
+ }
+ else
+ {
+ throw (BridgeException) e;
+ }
+ }
+ finally
+ {
+ dumpScopeId(scopeId, "ACTION_PHASE");
+
+ if (context != null)
+ {
+ // remove the redirect attr so its not carried over to the
+ // render in environments in which action/render are run in the
+ // same request ctx. There are two potential attrs -- the one on
+ // the request holds info if a redirect occurred within this request
+ // The one on the session caches the redirect that occurred during render
+ // so it can be used in subsequent renders that occur before the action.
+ context.getExternalContext().getRequestMap().remove(BridgeImpl.REDIRECT_VIEWPARAMS);
+ context.getExternalContext().getSessionMap().remove(BridgeImpl.RENDER_REDIRECT_VIEWPARAMS);
+ context.release();
+ }
+
+ // our servletrequestattributelistener uses this as an indicator of whether
+ // its actively working on a request -- remove it to indicate we are done
+ request.removeAttribute(Bridge.PORTLET_LIFECYCLE_PHASE);
+ }
+ }
+
public void doFacesRequest(RenderRequest request, RenderResponse response)
throws BridgeException,
@@ -509,7 +700,7 @@
// FacesContext in case anything in the context construction relies
// on these restored values.
// don't restore scope if mode changed
- scopeId = request.getParameter(REQUEST_SCOPE_ID_RENDER_PARAM);;
+ scopeId = request.getParameter(REQUEST_SCOPE_ID_RENDER_PARAM);
if (scopeId != null)
{
// Its possible we didn't detect the mode change but its the wrong scope
@@ -670,8 +861,8 @@
// ViewRoot should always = null in the resourec case
if (context.getViewRoot() == null)
{
- // add self as PhaseListener to prevent action phases from
- // executing when running in a render (vs. a resource) request
+ // 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
@@ -755,7 +946,7 @@
{
if (BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RESOURCE_PHASE)
{
- saveBridgeRequestScopeData(context,scopeId, preExistingAttributes);
+ saveBridgeRequestScopeData(context, scopeId, preExistingAttributes);
}
updateViewInfo(context, scopeId);
}
@@ -853,8 +1044,6 @@
scopeId = initBridgeRequestScope(request, null);
}
- restoreBridgeRequestScopeData(request, scopeId);
-
FacesContext context = null;
try
{
@@ -1414,7 +1603,7 @@
return scopeId;
}
- private String initBridgeRequestScope(ClientDataRequest request, StateAwareResponse response)
+ private String initBridgeRequestScope(PortletRequest request, StateAwareResponse response)
{
// Generate an RMI UID, which is a unique identifier WITHIN the local
@@ -1472,6 +1661,26 @@
requestScopeMap = createRequestScopeMap(portletContext);
portletContext.setAttribute(REQUEST_SCOPE_MAP, requestScopeMap);
}
+
+ if (BridgeUtil.getPortletRequestPhase() == Bridge.PortletPhase.RESOURCE_PHASE)
+ {
+ // Because we didn't restore them at the beginning of the request
+ // Merge any existing scope attributes that weren't written during this request
+ Map<String, Object> existing = requestScopeMap.get(scopeId);
+ if (existing != null)
+ {
+ Iterator<Map.Entry<String, Object>> i = existing.entrySet().iterator();
+ while (i.hasNext())
+ {
+ Map.Entry<String, Object> e = i.next();
+ if (!o.containsKey(e.getKey()))
+ {
+ o.put(e.getKey(), e.getValue());
+ }
+ }
+ }
+ }
+
requestScopeMap.put(scopeId, o);
}
}
@@ -1951,7 +2160,14 @@
FacesContext context = event.getFacesContext();
// Now restore the Faces Messages
restoreFacesMessageState(context);
- context.renderResponse();
+
+ switch (BridgeUtil.getPortletRequestPhase())
+ {
+ case RENDER_PHASE:
+ case EVENT_PHASE:
+ // skip rest of action processing
+ context.renderResponse();
+ }
}
}
Modified: myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java
URL: http://svn.apache.org/viewvc/myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java?rev=725844&r1=725843&r2=725844&view=diff
==============================================================================
--- myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java (original)
+++ myfaces/portlet-bridge/core/trunk_2.0.x/impl/src/main/java/org/apache/myfaces/portlet/faces/context/PortletExternalContextImpl.java Thu Dec 11 14:24:19 2008
@@ -57,6 +57,7 @@
import javax.portlet.PortletURL;
import javax.portlet.RenderResponse;
import javax.portlet.ResourceURL;
+import javax.portlet.StateAwareResponse;
import javax.portlet.WindowState;
import javax.portlet.faces.Bridge;
import javax.portlet.faces.BridgeDefaultViewNotSpecifiedException;
@@ -370,9 +371,10 @@
url = baseURL.toString();
url = url.replaceAll("\\&\\;", "&");
}
- else
+ else if (getPortletPhase() == Bridge.PortletPhase.ACTION_PHASE ||
+ getPortletPhase() == Bridge.PortletPhase.EVENT_PHASE)
{ // action - write the viewId to navigational state
- ActionResponse actionResponse = (ActionResponse) getResponse();
+ StateAwareResponse stateResponse = (StateAwareResponse) getResponse();
// set request params into navigational states
Enumeration<String> list = queryStr.getParameterNames();
@@ -383,7 +385,7 @@
{
try
{
- actionResponse.setPortletMode(new PortletMode(queryStr.getParameter(param)));
+ stateResponse.setPortletMode(new PortletMode(queryStr.getParameter(param)));
}
catch (Exception e)
{
@@ -401,7 +403,7 @@
{
try
{
- actionResponse.setWindowState(new WindowState(queryStr.getParameter(param)));
+ stateResponse.setWindowState(new WindowState(queryStr.getParameter(param)));
}
catch (Exception e)
{
@@ -414,7 +416,7 @@
}
else
{
- actionResponse.setRenderParameter(param, queryStr.getParameter(param));
+ stateResponse.setRenderParameter(param, queryStr.getParameter(param));
}
}
}