Did you get the error in the title? This is a very common occurrence in JSF (Java Server Faces) applications. It is easy to get and easy to get rid off, you just have to be careful.
Here is a full error stacktrace:
javax.faces.FacesException: Faces context not found. getResponseWriter will fail. Check if the FacesServlet has been initialized at all in your web.xml configuration fileand if you are accessing your jsf-pages through the correct mapping. E.g.: if your FacesServlet is mapped to *.jsf (with the
-element), you need to access your pages as 'sample.jsf'. If you tried to access 'sample.jsp', you'd get this error-message. Javax.faces.webapp.UIComponentTag.setupResponseWriter(UIComponentTag.java:926) javax.faces.webapp.UIComponentTag.doStartTag(UIComponentTag.java:313) org.apache.myfaces.taglib.core.ViewTag.doStartTag(ViewTag.java:73) org.apache.jsp.index_jsp._jspx_meth_f_005fview_005f0(index_jsp.java:92) org.apache.jsp.index_jsp._jspService(index_jsp.java:67) org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70) javax.servlet.http.HttpServlet.service(HttpServlet.java:717) org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:377) org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313) org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260) javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
Why it appears: well, that is simple. It occurs when the FacesContext object is not found in the session. This object must be already in the session before the first JSF tag is processed (usually a f:view tag). We will analyse the situations when this object is missing.
JSF functionality revolves around a special servlet, called FacesServlet. The servlet is defined in the web.xml file. It can be initialized using various patterns, some popular ones being *.jsf, *.faces or /faces/*. When the servlet is accessed, it ensures the FacesContext object exist in the session, if not will ensure it will be created.
When a brand new session is started, the FacesContext does not exist. If you access a page with JSF tags and the FacesContext does not exist, you get the error.
There are two situations:
The application context is accessed
- The welcome page will be then loaded.
- This page must be a resource existent in the war, probably a jsp page. If the page contains JSF tags, because the faces servlet was not invoked, you get the error
The solution for this: The landing page will contain ONLY a
A bookmark is accessed
The user bookmarked one of the pages inside the application. If the session is brand new and the bookmarks do not trigger the faces servlet, then the error gets displayed.
Solution: obviously the user bookmarked an internal application link. If the internal link would have triggered the faces servlet (being for example in the format *.jsf) then the error would not have appeared. It is obvious then that all the internal links should trigger the faces servlet - consistently use *.jsf internal links rather than *.jsp and the problem is solved.
This is a little bit different than the previous, with the same result as the situation in which a bookmark is used.
- In this case, there was a valid session, the user spent some time operating the application then for some reason the session was left to expire.
- Then the operator issues another application request. In this case, if there is some security implementation in place, the application must forward to the login page with an error message "session expired, please log back in".
- However the FacesContext also vanished and instead of the above mentioned flow, instead of seeing the login page together with the error message, we get to see the one related to the missing FacesContext object.
- The solution is identical with the one above: all the internal links (and the forwards) must point to urls targeting the faces servlet. Always page.jsf, never page.jsp
- FacesContext is required for the entire life of a JSF session
- The welcome page should access the faces servlet - usually forwarding to an URL with the faces servlet URL pattern. This creates the faces context object if is not existent
- All the other internal links should follow the faces servlet URL pattern. In this way Faces Context will be recreated if needed - especially if it is accidentally destroyed by a session expiration