title: Custom 404 error page not working with Struts 2
body: <p>I am converting a JSP/Servlet dynamic web project to Struts 2 and the custom error pages (that previously worked with the JSP/Servlet version) have stopped working.</p>
  
  <p>When I induce a 404 error by accessing a non-existent page like <code>abc.jsp</code>, it throws below exception:</p>
  
  <pre><code>SEVERE: Servlet.service() for servlet jsp threw exception
  The Struts dispatcher cannot be found.  This is usually caused by using Struts tags without the associated filter. Struts tags are only usable when the request has passed through its servlet filter, which initializes the Struts dispatcher needed for this tag. - [unknown location]
      at org.apache.struts2.views.jsp.TagUtils.getStack(TagUtils.java:60)
      at org.apache.struts2.views.jsp.StrutsBodyTagSupport.getStack(StrutsBodyTagSupport.java:44)
      at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:48)
      at org.apache.jsp._404_jsp._jspx_meth_s_005finclude_005f0(_404_jsp.java:111)
      at org.apache.jsp._404_jsp._jspService(_404_jsp.java:71)
      at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
      at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
      at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
      at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
      at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
      at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488)
      at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
      at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
      at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:467)
      at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:338)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:203)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
      at java.lang.Thread.run(Unknown Source)
  
  Nov 18, 2014 11:14:56 PM org.apache.catalina.core.StandardHostValve custom
  SEVERE: Exception Processing ErrorPage[errorCode=404, location=/404.jsp]
  org.apache.jasper.JasperException: An exception occurred processing JSP page /404.jsp at line 6
  
  3: &lt;html&gt;
  4: &lt;head&gt;
  5: &lt;title&gt;My Site - WHOOPS!&lt;/title&gt;
  6: &lt;s:include value="css/style2.css" /&gt;
  7: &lt;/head&gt;
  8: 
  9: &lt;body class="errorpage"&gt;
  
  
  Stacktrace:
      at org.apache.jasper.servlet.JspServletWrapper.handleJspException(JspServletWrapper.java:568)
      at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:470)
      at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:390)
      at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:334)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
      at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
      at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
      at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:748)
      at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:488)
      at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:411)
      at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:338)
      at org.apache.catalina.core.StandardHostValve.custom(StandardHostValve.java:467)
      at org.apache.catalina.core.StandardHostValve.status(StandardHostValve.java:338)
      at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:203)
      at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
      at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
      at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
      at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
      at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
      at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
      at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:314)
      at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
      at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
      at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
      at java.lang.Thread.run(Unknown Source)
  Caused by: The Struts dispatcher cannot be found.  This is usually caused by using Struts tags without the associated filter. Struts tags are only usable when the request has passed through its servlet filter, which initializes the Struts dispatcher needed for this tag. - [unknown location]
      at org.apache.struts2.views.jsp.TagUtils.getStack(TagUtils.java:60)
      at org.apache.struts2.views.jsp.StrutsBodyTagSupport.getStack(StrutsBodyTagSupport.java:44)
      at org.apache.struts2.views.jsp.ComponentTagSupport.doStartTag(ComponentTagSupport.java:48)
      at org.apache.jsp._404_jsp._jspx_meth_s_005finclude_005f0(_404_jsp.java:111)
      at org.apache.jsp._404_jsp._jspService(_404_jsp.java:71)
      at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
      at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
      at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:432)
      ... 23 more
  </code></pre>
  
  <p>Below is my project structure:</p>
  
  <p><img src="https://i.stack.imgur.com/Wab9K.png" alt="customerror"></p>
  
  <p><strong>web.xml:</strong></p>
  
  <pre><code>&lt;?xml version="1.0" encoding="UTF-8"?&gt;
  &lt;web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns="http://java.sun.com/xml/ns/javaee"
      xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
      id="WebApp_ID" version="3.0"&gt;
      &lt;display-name&gt;My Site&lt;/display-name&gt;
  
      &lt;welcome-file-list&gt;
          &lt;welcome-file&gt;index.jsp&lt;/welcome-file&gt;
          &lt;welcome-file&gt;default.jsp&lt;/welcome-file&gt;
      &lt;/welcome-file-list&gt;
  
      &lt;error-page&gt;
          &lt;error-code&gt;404&lt;/error-code&gt;
          &lt;location&gt;/404.jsp&lt;/location&gt;
      &lt;/error-page&gt;
  
      &lt;error-page&gt;
          &lt;error-code&gt;500&lt;/error-code&gt;
          &lt;location&gt;/500.jsp&lt;/location&gt;
      &lt;/error-page&gt;
  
      ...
  
      &lt;filter&gt;
          &lt;filter-name&gt;struts2&lt;/filter-name&gt;
          &lt;filter-class&gt;org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter&lt;/filter-class&gt;
      &lt;/filter&gt;
  
      &lt;filter-mapping&gt;
          &lt;filter-name&gt;struts2&lt;/filter-name&gt;
          &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
      &lt;/filter-mapping&gt;
  &lt;/web-app&gt;
  </code></pre>
  
  <p><em>How do I make the custom error pages work with Struts 2?</em></p>