1
votes

I am implementing a custom 404 handler in JSP - AEM, CQ. The file lives in apps/sling/servlet/errorhandler/404.jsp

I am intercepting the request for Not Found and forwarding using RequestDispatcher class.

<%@taglib prefix="sling" uri="http://sling.apache.org/taglibs/sling"%>
<sling:defineObjects />
<%
    // setting response code as 404
    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.setStatus(404);
System.out.println(response.getStatus());
        try {
            RequestDispatcher rd = request.getRequestDispatcher("/error-page.html");

            rd.forward(request, response);


        } catch (Exception e) {
            RequestDispatcher rd = request.getRequestDispatcher("/error-page.html");
            rd.forward(request, response);

        }

%>

The above code gets the content of error-page.html keeping the URL same, but the response code sent back is not 404. It is 200 instead.

How can I return a 404?

1
if you are forwarding to an error page (and the error page exists), you are bound to get a 200, right? - blurfus
I think so too, I tried to include(req, res) but still 200. - shank
what is the point of sending 404 error code as you have already intercepted it and sent a genetic 404 error page. You could just log the error message and continue ? I fail to understand the reason behind it. - Madhu V Rao
This is custom page that I am trying to send, and it will based on the users location. - shank
Not an answer to your question, but as an aside — error handling can be tricky to nail in Sling/AEM, as sometimes the page your including can overwrite the status code that you've set. Where it does this is non-obvious (if you're extending the default Page supertype), as it's knitted into the libs directory. I'd suggest using something like the ACS Commons Error Page Handler plugin to take the pain out of it - anotherdave

1 Answers

3
votes

Using #include rather than #forward will allow you to return a 404:

response.setStatus(HttpServletResponse.SC_NOT_FOUND);
RequestDispatcher dispatcher = request.getRequestDispatcher(path);
dispatcher.include(request,response);

I would suggest creating a Java Servlet rather than using JSP:

@SlingServlet(metatype = true, resourceTypes = {"/apps/sling/servlet/errorhandler"}, extensions = {"404"})
public class ErrorServlet extends SlingSafeMethodsServlet {

    @Override
    protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response) throws ServletException, IOException {
        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
        RequestDispatcher dispatcher = request.getRequestDispatcher("myPath");
        dispatcher.include(request,response);
    }
}

Are you checking for the status code in AEM directly or are you checking after Apache and Dispatcher?