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]