title: Use a servlet for custom HTTP errors? (Tomcat)
body: <p>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.</p>
  
  <p>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.  </p>
  
  <p>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).</p>
  
  <p>Here is a sample error:</p>
  
  <pre><code>    :: 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)
  </code></pre>