July 24th, 2009 by Lincoln Baxter III

Please! Tell your developers to call facesContext.release()

If you are manipulating any FacesContext when doing any kind of Sevlet Forwards – such as from a filter – you MUST release() any FacesContext you’ve created. The consequences of forgetting this are potentially dire. You may even want to go so far as to completely UN-set the FacesContext from the current thread. We would do this by calling FacesContextBuilder.removeFacesContext()

Call FacesContext.release() when you are done!

 

FacesContextBuilder.java

public class FacesContextBuilder
{
    public FacesContext getFacesContext(final ServletRequest request, final ServletResponse response)
    {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (facesContext != null)
        {
            return facesContext;
        }
 
        FacesContextFactory contextFactory = (FacesContextFactory) FactoryFinder
                .getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
        LifecycleFactory lifecycleFactory = (LifecycleFactory) FactoryFinder
                .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
        Lifecycle lifecycle = lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
 
        ServletContext servletContext = ((HttpServletRequest) request).getSession().getServletContext();
        facesContext = contextFactory.getFacesContext(servletContext, request, response, lifecycle);
        InnerFacesContext.setFacesContextAsCurrentInstance(facesContext);
 
        return facesContext;
    }
 
    public void removeFacesContext()
    {
        InnerFacesContext.setFacesContextAsCurrentInstance(null);
    }
 
    private abstract static class InnerFacesContext extends FacesContext
    {
        protected static void setFacesContextAsCurrentInstance(final FacesContext facesContext)
        {
            FacesContext.setCurrentInstance(facesContext);
        }
    }
 
}
  FacesContext wraps the HttpServletRequest with its own RequestWrapper, and when attempting to hold on to references to any response through a Servlet Forward (via RequestDispatcher), bad things will happen.

For example:

When using the PrettyFaces URL bookmarking/rewriting utility (who’s PrettyFilter relies on Servlet forwards) any FacesContext created before this forward occurs will be left open, and sporadic NullPointerExceptions will occur depending on Request thread timing in the Servlet container.  
Caused by: java.lang.NullPointerException
at org.apache.catalina.connector.Request.setAttribute(Request.java:1424)
at org.apache.catalina.connector.RequestFacade.setAttribute(RequestFacade.java:503)
at javax.servlet.ServletRequestWrapper.setAttribute(ServletRequestWrapper.java:284)
at com.ocpsoft.pretty.PrettyContext.setCurrentInstance(PrettyContext.java:93)
at com.ocpsoft.pretty.PrettyContext.getCurrentInstance(PrettyContext.java:84)
at com.ocpsoft.pretty.PrettyFilter.doFilter(PrettyFilter.java:58)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
...
  Or sometimes request attributes will be missing entirely, even if the request is accessible.   In order to safely navigate FacesContext in a ServletFilter, make absolutely sure that you release() and remove the context when you are done with it. Then you get happy applications working together with other frameworks!   Cheers, happy developing! 🙂

Posted in JSF

8 Comments

  1. TomEuchre says:

    Lincoln,

    Thanks for the tip. We were using J2EE webapp to house our Flex SWFs, which communicated through the webapp framework to request data from another server via webservices. The SWF would do a RemoteObject call over BlazeDS to our backing bean method, which invoked the webapp framework query. A valid Session and FacesContext were required, but of course none existed. In JSF1.1 we created the context in the doFilter chain, but when we moved to JSF1.2 we got NPEs all over (not under Tomcat – only under Websphere 7).

    We were already setting a UIViewRoot (to a dummy string view) in the JSF1.1 version, so I don’t know if that will make a difference for us. Any other ideas?

    We had to revert to JSF1.1/Websphere 6.1 to get it working again.

    1. Lincoln says:

      It’s very difficult to say what your problem could be without more information, or seeing it :/ Where are the NPE’s occurring? At what stage of the request?

  2. Pramod says:

    Awesome article. I had the NPE with the FacesContext which was reference in one of the functionality. This article helped in getting rid of the NPE and get the context which was missing.

  3. I’m having similar problem but with session following is the exception i got. my environment is jboss eap 4.3 on linux with jsf 1.2

    java.lang.NullPointerException
    at com.sun.faces.context.SessionMap.put(ExternalContextImpl.java:970)

  4. Søren Lund says:

    Thank you, that saved my day. Got weird exceptions (when trying to access the SessionMap). But release() and remove solved that.

    I was using a servlet (from an ajax call) the server was extended from the abstract class described here:
    https://cwiki.apache.org/MYFACES/access-facescontext-from-servlet.html

    I also updated that wiki page.

  5. alvaro tovar says:

    thanks

  6. Mathieu says:

    After hours of research on the internet and effort about my NPE I finally end up here. Thanks a lot for your post.

  7. Raphael Patricio says:

    I didn’t undesrtand what happens in "sporadic NullPointerExceptions will occur depending on Request thread timing in the Servlet container." Why it happens?

Reply to Søren Lund




Please note: In order to submit code or special characters, wrap it in

[code lang="xml"][/code]
(for your language) - or your tags will be eaten.

Please note: Comment moderation is enabled and may delay your comment from appearing. There is no need to resubmit your comment.