Wednesday, February 17, 2010

JSF 1.2 + JSP and Facelets error - java.lang.RuntimeException: Cannot find FacesContext

I've just finished installing Facelets on my JSF 1.2 tutorial when I got this error message:
HTTP Status 500 -

type Exception report

message

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

org.apache.jasper.JasperException: An exception occurred processing JSP page /index.jsp at line 13

10: <%@page import="java.util.List"%>
11: <%@page import="identity.Identifiable"%>
12: <%@page import="name.Nameable"%>
13: <f:view>
14: <html>
15: <head>
16: <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">


Stacktrace:
 org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:505)
 org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:416)
 org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
 org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

root cause

java.lang.RuntimeException: Cannot find FacesContext
 javax.faces.webapp.UIComponentClassicTagBase.getFacesContext(UIComponentClassicTagBase.java:1855)
 javax.faces.webapp.UIComponentClassicTagBase.setJspId(UIComponentClassicTagBase.java:1672)
 org.apache.jsp.index_jsp._jspService(index_jsp.java:93)
 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:374)
 org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:342)
 org.apache.jasper.servlet.JspServlet.service(JspServlet.java:267)
 javax.servlet.http.HttpServlet.service(HttpServlet.java:717)

note The full stack trace of the root cause is available in the Apache Tomcat/6.0.20 logs.
Apache Tomcat/6.0.20
This happens because:
  • I've added Facelets to the web project
  • I have set up the JSF default suffix to *.xhtml and JSF view technology to Facelets
  • I have a JSF+JSP page
This exact question on java.net Forums : Is that possible/good to mix the ... leads to this FAQ on How do I use Facelets and JSP in the same application?:
You have to use prefix mapping for the Facelets pages in order for this to work. Leave the DEFAULT_SUFFIX with the JSF default of .jsp. Configure the Facelet's VIEW_MAPPINGS parameter:
<web-app>
  <context-param>
    <param-name>javax.faces.DEFAULT_SUFFIX</param-name>
    <param-value>.jsp</param-value>
  </context-param>

  <!-- Facelets pages will use the .xhtml extension -->
  <context-param>
    <param-name>facelets.VIEW_MAPPINGS</param-name>
    <param-value>*.xhtml</param-value>
  </context-param>     

  <servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
  </servlet>
 
  <!-- Use prefix mapping for Facelets pages, e.g. http://localhost:8080/webapp/faces/mypage.xhtml -->
  <servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
  </servlet-mapping>
</web-app>
The best way is, of course... to get rid of JSP pages and use Facelets exclusively. :-)

But at least now you know you have a choice. :-)

If you're still using JSF 1.2 I heavily recommend you to upgrade to JSF 2.0 as soon as possible. Check out the book JavaServer Faces 2.0, The Complete Reference which is a great resource on using JSF 2.0.