Please! Tell your developers to call facesContext.release()
LincolnIf 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! ![]()
![]() | About the author:Lincoln Baxter, III is a Senior Software Engineer at Red Hat, Inc., working on JBoss open-source projects. This blog represents his personal thoughts and perspectives, not necessarily those of his employer. He is a founder of OcpSoft, the author of PrettyFaces: bookmarking, SEO extensions for JSF, and an individual member of the JavaServer™ Faces Expert Group. When he is not swimming, running, or playing Ultimate Frisbee, Lincoln is focused on promoting open-source software and making web-applications more accessible for small businesses, individuals. His latest project is ScrumShark, an open-source, agile project management tool. |
Posted in JSF

