Close

Spring Boot - Mapping Errors in Servlet based application outside of Spring MVC

[Updated: Mar 13, 2018, Created: Mar 13, 2018]

Applications that do not use Spring MVC, ErrorPageRegistrar interface can be used to directly map errors.

Example

In this Servlet based example, we are going to create Servlets and will map errors with Boot's ErrorPageRegistrar.

An application Servlet

@WebServlet(name = "appServlet", urlPatterns = "/app/*")
public class MyAppServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
      String requestURI = req.getRequestURI();
      if (requestURI.endsWith("test")) {
          throw new RuntimeException("test exception from "+requestURI);
      } else if (requestURI.endsWith("test2")) {
          throw new ServletException("test servlet exception");
      } else {
          resp.getWriter().println("Response from appServlet at " + requestURI);
      }
  }
}

Implementing ErrorPageRegistrar

@Component
public class MyErrorPageRegistrar implements ErrorPageRegistrar {

  @Override
  public void registerErrorPages(ErrorPageRegistry registry) {
      registry.addErrorPages(
              createNotFoundErrorPage(),
              createRuntimeExceptionPage(),
              createOtherErrorPage());
  }

  private ErrorPage createNotFoundErrorPage() {
      return new ErrorPage(HttpStatus.NOT_FOUND, "/notFoundServlet");
  }

  private ErrorPage createRuntimeExceptionPage() {
      return new ErrorPage(RuntimeException.class, "/runtimeExceptionHandler");
  }

  private ErrorPage createOtherErrorPage() {
      return new ErrorPage(Throwable.class, "/WEB-INF/internal-error.jsp");
  }
}

The Error Handler Servlets

@WebServlet(name = "not-found-error-servlet", urlPatterns = "/notFoundServlet")
public class NotFoundServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
      resp.setContentType("text/html");
      PrintWriter writer = resp.getWriter();
      writer.write("<h2>Page not found </h2>");
      String requestUri = (String) req.getAttribute("javax.servlet.error.request_uri");
      writer.write("request uri: " + requestUri);
      writer.write("<br>Response from "+this.getClass());
  }
}
@WebServlet(name = "runtime-handler-servlet", urlPatterns = "/runtimeExceptionHandler")
public class RuntimeExceptionServlet extends HttpServlet {
  @Override
  protected void doGet(HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {

      resp.setContentType("text/html");
      PrintWriter writer = resp.getWriter();
      writer.write("<h2>RuntimeException</h2>");

      String requestUri = (String) req.getAttribute(RequestDispatcher.ERROR_REQUEST_URI);
      writer.write("request uri: " + requestUri);
      Integer code = (Integer) req.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
      writer.write("<br>status code: " + code);
      String errorMessage = (String) req.getAttribute(RequestDispatcher.ERROR_MESSAGE);
      writer.write("<br>error message: " + errorMessage);
      writer.write("<br>Response from "+this.getClass());
  }
}

The JSP Page

/src/main/webapp/WEB-INF/internal-error.jsp

<h3>Error on server side</h3>
<p>
    <%= request.getAttribute("javax.servlet.error.exception") %>
</p>
<p>From jsp page.</p>

Boot main class

@SpringBootApplication
@ServletComponentScan
public class SpringBootMain extends SpringBootServletInitializer {

  @Override
  protected SpringApplicationBuilder configure (SpringApplicationBuilder builder) {
      return builder.sources(SpringBootMain.class);
  }

  public static void main(String[] args) {
      SpringApplication.run(SpringBootMain.class);
  }
}

Check out this tutorial to understand why @ServletComponentScan is needed in above class.

Output

To try examples, run spring-boot maven plugin (configured in pom.xml of example project below):

mvn spring-boot:run

The above example application will also work, if we deploy it to a server or execute it as a war.

Also check out how to map errors in a Servlet application without Boot.

Example Project

Dependencies and Technologies Used:

  • Spring Boot 2.0.0.RELEASE
    Corresponding Spring Version 5.0.4.RELEASE
  • spring-boot-starter-web : Starter for building web, including RESTful, applications using Spring MVC. Uses Tomcat as the default embedded container.
  • spring-boot-starter-tomcat : Starter for using Tomcat as the embedded servlet container. Default servlet container starter used by spring-boot-starter-web.
  • tomcat-embed-jasper 8.5.28: Core Tomcat implementation.
  • jstl 1.2 javax.servlet:jstl
  • JDK 1.8
  • Maven 3.3.9

Mapping Error Pages outside of Spring MVC Examples Select All Download
  • boot-servlet-error-page-mapping
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyErrorPageRegistrar.java
          • webapp
            • WEB-INF

    See Also