0

I'm using Struts 1.3.10 to run a site. Everything works well, but I'd like to add some custom error handling for the HTTP 404 and other such errors. Everywhere I look, I see that the custom error pages should be jsp's (e.g. 404.jsp) that are defined in the Web.xml file.

In my app, I've created a global error handler which uses an error handling servlet to display a dynamic error page for other servlet errors (e.g. runtime, bus logic, etc.). Would there be anything wrong with redirecting to this servlet from a 404.jsp (as defined in the Web.xml)? the idea would be to hit the 404.jsp, get redirected to the servlet do the logging I want, then show the error page. I'd like to log what caused the error in the first place, such as the IP, the requested URI, generate list of IPs to block, etc.

I did try this, and in principle it works... trouble is that I sometimes get illegal state errors ... I'm wondering if the approach is wrong or this is just a bad idea??? I get a lot of 404's from IP's trolling for misconfigured PHP sites it seems (see below).

Here is a sample error:

    :: HTTP 404 ERROR -- page not found.  URL requested = /scripts/setup.php
2012-01-09 20:23:39,375 | ERROR | (ApplicationDispatcher.java:691) - Servlet.service() for servlet jsp threw exception
java.lang.IllegalStateException
    at org.apache.catalina.connector.ResponseFacade.sendRedirect(ResponseFacade.java:433)
    at org.apache.struts.taglib.logic.RedirectTag.doRedirect(RedirectTag.java:314)
    at org.apache.struts.taglib.logic.RedirectTag.doEndTag(RedirectTag.java:268)
    at org.apache.jsp._404_jsp._jspx_meth_logic_005fredirect_005f0(_404_jsp.java:118)
    at org.apache.jsp._404_jsp._jspService(_404_jsp.java:74)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:98)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:369)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:308)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:259)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:659)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311)
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:364)
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:285)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
    at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:200)
    at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
    at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:775)
    at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:704)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:897)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
    at java.lang.Thread.run(Thread.java:619)
Jan 9, 2012 8:23:39 PM org.apache.catalina.core.StandardHostValve custom
SEVERE: Exception Processing ErrorPage[errorCode=404, location=/404.jsp]
org.apache.jasper.JasperException
    at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:498)
    at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:405)
    at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:308)
    at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:259)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:269)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:188)
    at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:659)
    at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:459)
    at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:395)
    at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:311)
    at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:364)
    at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:285)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:137)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:117)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:108)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:174)
    at org.apache.jk.server.JkCoyoteHandler.invoke(JkCoyoteHandler.java:200)
    at org.apache.jk.common.HandlerRequest.invoke(HandlerRequest.java:291)
    at org.apache.jk.common.ChannelSocket.invoke(ChannelSocket.java:775)
    at org.apache.jk.common.ChannelSocket.processConnection(ChannelSocket.java:704)
    at org.apache.jk.common.ChannelSocket$SocketConnection.runIt(ChannelSocket.java:897)
    at org.apache.tomcat.util.threads.ThreadPool$ControlRunnable.run(ThreadPool.java:689)
    at java.lang.Thread.run(Thread.java:619)
user991945
  • 103
  • 1
  • 3
  • 14

1 Answers1

3

You shouldn't control the request/response inside a JSP. A JSP is basically part of the response. Attempting to change the response inside a JSP may lead to illegal state exceptions when the response is already committed. In general, writing raw Java code and/or controlling the request/response in a JSP is a poor practice.

Just map the error page location to a servlet directly.

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

where /someErrorServlet matches the <url-pattern> of your error handling servlet. In there, you've all the freedom to control the request/response, such as forwarding to an arbitrary JSP.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I like this, and it'll scale to all errors it seems, allowing me to handle each error specifically in the errorHandler. However, should a 503 error be a page rather than a servlet? I'm thinking that if it's in fact a true internal error, the servlet may be compromised and not fire. – user991945 Jan 10 '12 at 19:55
  • It can be a servlet, but logging of exceptions (the 5nn errors) should be done by a `Filter`. Basically just put `chain.doFilter(request, response)` inside a `try-catch`. – BalusC Jan 10 '12 at 20:01