Question

I work on a JSF application powered by Tomcat 7.0.35. I would like to create a custom error page and have therefore played with the <error-page> tag in the web.xml configuration file.

<error-page>
    <error-code>404</error-code>
    <location>/error</location>
</error-page>

It seems to work in the sense that in case of a 404, the page returned has the correct HTTP body. However the HTTP return code is 200. The expected 404 was correctly received when <error-page> was not configured.

The same soft-404 problem happens if <error-code> is not specified.

<error-page>
    <location>/error</location>
</error-page>

I am looking for a way to configure this error page without losing the error code.

Two more pieces of information that might be useful :

  • The JSF project stage is Production
  • Pretty URLs are being handled by Pretty Faces 3.3.3 with the following

    @Named(value = "error")
    @RequestScoped
    @URLMappings(mappings = {
        @URLMapping(id = "error", pattern = "/error", viewId = "/faces/error.xhtml")})
    public class ErrorController implements Serializable {
    
Was it helpful?

Solution

Sometimes containers do not seem to behave very nicely when you have an Error page handled by a servlet filter. In this case it looks like you probably have mapped "/error" with PrettyFaces, and are forwarding that internally to another resource. (PrettyFaces works with Servlet forwards)

I believe what occurs here, is the container sees that new Forward, forgets that it was actually showing an error page, and sends a 200 status because the Forwarded request was successful.

What you will need to do to resolve this, is add an <action>#{bean.send404}</action> that sets the 404 status in your error page prettyfaces mapping.

<url-mapping>
   <pattern value="/error" />
   <view-id="/faces/error.xhtml" />
   <action>#{bean.send404}</action>
</url-mapping>

Then your bean method will need to get a hold of the HttpServletResponse, which ou can usually get from the FacesContext:

HttpServletResponse response = (HttpServletResponse)FacesContext.getCurrentInstance()
         .getExternalContext().getResponse();
response.sendError(HttpServletResponse.SC_NOT_FOUND);

That should do the trick for you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top