JSF portlet bridge 1.0.0 implementation works incorrectly in a multi-user 
environment
-------------------------------------------------------------------------------------

                 Key: PB-108
                 URL: https://issues.apache.org/jira/browse/PB-108
             Project: Portals Bridges
          Issue Type: Bug
          Components: jsf
         Environment: MyFaces JSF 1.2 and Vignette Portal
            Reporter: Leonid Elkun


We have a Vignette / MyFaces 1.2 / portlet-bridge-1.0.0-beta based web 
application. When the development had started we've downloaded the latest 
version of the bridge at the time (roughly 08-2009) and still using this 
version.
After we started testing in a multi-user environment it had become clear that 
the bridge periodically corrupts incoming action (but not render) portal 
requests. The corresponding buggy code and fixes are described below.

1. Defective code
The following 2 methods wrongly assume that temporary registration of the 
bridge instance as a phase listerner while executing a render request doesn't 
affect concurrent action request (s) execution through the same instance. In 
reality a concurrent action request can sneak in between the 
lifecycle.addPhaseListener(this) and lifecycle.removePhaseListener(this) calls 
and end prematuraly just after the RESTORE_VIEW JSF phase (because of the 
context.renderResponse() call).

private void doFacesRender(
      RenderRequest request,
      RenderResponse response,
      FacesContext context,
      Lifecycle lifecycle,
      String scopeId,
      List <String> preExistingAttributes
      )
    throws BridgeException, BridgeUninitializedException, NullPointerException
  {
    ...
    if (context.getViewRoot() == null)
    {
      ...
      lifecycle.addPhaseListener(this);
      try
      {
        lifecycle.execute(context);
      }
      catch (Exception e)
      {
        ...
      }
      finally
      {
        lifecycle.removePhaseListener(this);
      }
    }
...
}

public void afterPhase(PhaseEvent event)
  {
    // only set renderresponse if in RESTORE_VIEW phase



    if (event.getPhaseId() == PhaseId.RESTORE_VIEW)
    {
      FacesContext context = event.getFacesContext();
      // Now restore the Faces Messages
      restoreFacesMessageState(context);
      context.renderResponse();
    }
  }

2. Fixed code
We've implemented and successfully tested the following fixes.

private void doFacesRender(
      RenderRequest request,
      RenderResponse response,
      FacesContext context,
      Lifecycle lifecycle,
      String scopeId,
      List <String> preExistingAttributes
      )
    throws BridgeException, BridgeUninitializedException, NullPointerException
  {
    ...
    if (context.getViewRoot() == null)
    {
      ...
      //lifecycle.addPhaseListener(this);
      try
      {
        lifecycle.execute(context);
      }
      catch (Exception e)
      {
        ...
      }
      finally
      {
        //lifecycle.removePhaseListener(this);
      }
...
}

private synchronized Lifecycle getLifecycle()
    throws BridgeException
  {
    try
    {
      if (mLifecycle == null)
      {
        LifecycleFactory lifecycleFactory = 
          (LifecycleFactory) 
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
        String lifecycleId = 
          
mPortletConfig.getPortletContext().getInitParameter(FacesServlet.LIFECYCLE_ID_ATTR);
        if (lifecycleId == null)
        {
          lifecycleId = LifecycleFactory.DEFAULT_LIFECYCLE;
        }

        mLifecycle = lifecycleFactory.getLifecycle(lifecycleId);
        mLifecycle.addPhaseListener(this);
      }
      return mLifecycle;
    }
    catch (FacesException e)
    {
      Throwable rootCause = e.getCause();
      throw new BridgeException(e.getMessage(), rootCause);
    }
  }

public void afterPhase(PhaseEvent event)
  {
    if (BridgeUtil.getPortletRequestPhase().toString().contains("ACTION_PHASE"))
    {
        return;
    }
    if (event.getPhaseId() == PhaseId.RESTORE_VIEW)
    {
      FacesContext context = event.getFacesContext();
      // Now restore the Faces Messages
      restoreFacesMessageState(context);
      context.renderResponse();
    }
  }

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to