Search code examples
jsf-2http-status-code-404facelets

java.lang.NullPointerException at com.sun.faces.lifecycle.RestoreViewPhase.notifyAfter instead of HTTP 404 page not found


We are using JSF2.0.2 in weblogic10.3 , we are handling FileNotFound or Page Not Found in web.xml with 404 error page.

          webapp->             
                  folder-a->page1.xhtml
                            page2.xhtml

If we request a page which is not a inside folder-a , for example page3.xhtml ,then it is not caught by web.xml 404 ,instead it falls in to JSF layer and results in below exception.

java.lang.NullPointerException
    at com.sun.faces.lifecycle.RestoreViewPhase.notifyAfter(RestoreViewPhase.java:297)
    at com.sun.faces.lifecycle.RestoreViewPhase.doPhase(RestoreViewPhase.java:110)
    at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:114)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:308)

Solution

  • This is a bug in the early Mojarra version which will occur when you've a PhaseListener configured which should execute while restoring the view, but the UIViewRoot is null. This bug was introduced in Mojarra 2.0.4 and has been reported as issue 1764 and is been fixed since Mojarra version 2.1.0 as per the report (and 2.0.6 as per the source code). So, upgrading to at least that version should fix that problem.

    After you've upgraded Mojarra, you'll hit another problem. Mojarra doesn't send a 404 when the view is not found, but instead throws a com.sun.faces.context.FacesFileNotFoundException which is a subclass of java.io.FileNotFoundException. So this ends up as a HTTP 500 response. So if you configured the error page on error code of 404, then it won't be shown at all, but instead the error page on error code of 500 or the closest match on the exception type will be shown instead. You'd need to configure the error page as follows instead:

    <error-page>
        <exception-type>com.sun.faces.context.FacesFileNotFoundException</exception-type>
        <location>/errors/404.xhtml</location>
    </error-page>
    

    or if you don't want to be JSF implementation dependent

    <error-page>
        <exception-type>java.io.FileNotFoundException</exception-type>
        <location>/errors/404.xhtml</location>
    </error-page>