"Simple Software"

OcpSoft

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

July 24th, 2009 by Lincoln

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! :)

Post to Twitter Post to Delicious Post to Digg Post to StumbleUpon

Posted in JSF

Leave a Comment




Please note: In order to submit code or special characters, wrap it in <pre lang="java"> </pre> - 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.

Search

Recent Posts

Recent Comments

OcpSoft Agile Management

Recent Tweets:

Posting tweet...

Sponsored By:

Resources

Meta