Incorrect handling of FacesContext
----------------------------------

                 Key: MYFACES-1531
                 URL: https://issues.apache.org/jira/browse/MYFACES-1531
             Project: MyFaces Core
          Issue Type: Bug
    Affects Versions: 1.1.4
         Environment: WindowsXP & Solaris; Tomcat 5.5.17, Liferay 4.2.0 (Portal 
Server)
            Reporter: Olaf Fricke


We encountered some NPE when accessing the FacesContext in the doView-Method. I 
first thought about a bug in the Liferay-Portal-Server (see 
http://support.liferay.com/browse/LEP-1869). But then I discovered that it is a 
bug in MyFaces, that is triggred because Liferay pools ActionRequest and 
RenderRequest objects.

MyFaces changes the external context value in the method 
org.apache.myfaces.portlet.MyFacesGenericPortlet#facesRender to switch from 
ActionRequest and ActionResponse to RenderRequest and RenderResponse. But that 
switch happens to late, so that in doView (and doEdit and doHelp as well) the 
FacesContext uses references to the ActionRequest and ActionResponse instead of 
RenderRequest and RenderResponse. And unfortunately Liferay has already 
recycled the RenderRequest object and thus a NPE is raised when trying to use 
the request.

I added the following code to my portlet (indeed, to our own super class) to 
make the switch earlier and the NullPointerException when accessing attributes 
via the FacesContext will not be raised any longer. (Please note that I cannot 
use the FacesContext.getCurrentInstance() method in a portal environment, 
because each portlet owns its own context).

    public void render(RenderRequest request, RenderResponse response) throws 
PortletException,
            IOException {

        // The following code was taken from 
org.apache.myfaces.portlet.MyFacesGenericPortlet#facesRender
        //
        // get the portlet session local context
        ServletFacesContextImpl context = (ServletFacesContextImpl) 
request.getPortletSession()
                .getAttribute(CURRENT_FACES_CONTEXT);
        if (context != null) {
            // and set a new external context that uses the render request and 
response
            context.setExternalContext(makeExternalContext(request, response));
        } else {
            // no context available for the current portlet yet; create a new 
one and put it into the session
            context = (ServletFacesContextImpl) facesContext(request, response);
            request.getPortletSession().setAttribute(CURRENT_FACES_CONTEXT, 
context);
        }


        super.render(request, response);
    } 

Later I discovered another problem concerning the FacesContext: When rendering 
the very first MyFaces-Portlet, no FacesContext exists for the Portlet. 
Therefore the method nonFacesRequest is called. Somewhere inside this method a 
new FacesContext is created, but that new FacesContext is never put into the 
session. Thus my workaround in the render method was broken again. I fixed that 
by extending the method nonFacesRequest as follows:

    protected void nonFacesRequest(RenderRequest request, RenderResponse 
response)
            throws PortletException {

        super.nonFacesRequest(request, response);

        request.getPortletSession().setAttribute(CURRENT_FACES_CONTEXT,
                FacesContext.getCurrentInstance());
    }



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

Reply via email to