4

So, basically, I am able to create a custom error page using web.xml:

 <error-page>
     <error-code>404</error-code>
     <location>/WEB-INF/pages/error/404.jsp</location>
 </error-page>

But so far, in my project, I do not use web.xml and tend to use only java code.

Is there a proper and easy way to do like in web.xml but without using it (create custom error page)? And if there is no such way then would it be a bad move to add web.xml only for handling custom error pages?

THE Waterfall
  • 645
  • 6
  • 17
  • 1
    The community seems to feel that there is no way to do this according to https://stackoverflow.com/a/13450154/1840078. I'm inclined to agree - there are still a few use cases of `web.xml` for which no replacement Servlet 3.0+ annotation exists. I believe this is one of them. – Mark A. Fitzgerald Oct 20 '18 at 13:06
  • 1
    @MarkA.Fitzgerald Yes, that's actually what I was thinking of while googling. Thanks for kind of clarifying. – THE Waterfall Oct 20 '18 at 13:13
  • You're welcome, @THE Waterfall. Sorry I cannot provide a much better answer. It's hard to definitively show that something is _not_ possible. :) The only improvement I can think of is to scan through the Servlet spec (e.g. http://download.oracle.com/otndocs/jcp/servlet-3_1-fr-eval-spec/index.html) for words like 'page' and 'code' to see if any non-`web.xml` technique exists, but I suspect there is none. – Mark A. Fitzgerald Oct 20 '18 at 15:40

4 Answers4

0

This is what @ControllerAdvice does in Spring MVC

@ControllerAdvice
public class GlobalExceptionHandler {
   @ExceptionHandler({NoHandlerFoundException.class})
   @ResponseStatus(value = HttpStatus.NOT_FOUND)
   public void handleNotFound(HttpSession session, HttpServletRequest req, HttpServletResponse httpServletResponse, Exception ex) {
   }
}

Also add this line to your WebApplicationInitializer

public class CCPMWebAppInitializer implements WebApplicationInitializer {

  @Override
  public void onStartup(ServletContext servletContext) throws ServletException {

      // Create the 'root' Spring application context
      AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
      ....
       DispatcherServlet dispatcherServlet = new DispatcherServlet(rootContext);
       dispatcherServlet.setThrowExceptionIfNoHandlerFound(true);
      ...
  }
Jacob
  • 1,776
  • 14
  • 11
  • Should I add something in addition to class with @ControllerAdvice annotation? – THE Waterfall Oct 20 '18 at 13:10
  • No need, Spring will handle it. – Jacob Oct 20 '18 at 13:12
  • Am I missing something? I added `httpServletResponse.sendRedirect("/404");` in `handleNotFound` method and in some of the controllers I added `@RequestMapping` to handle `/404` to return custom page but I still doesn't work. Where am I mistaken? – THE Waterfall Oct 20 '18 at 13:17
  • Did you debug and see whether the method is called? – Jacob Oct 20 '18 at 13:21
  • Is the new class scanned by Spring i.e., covered by @ComponentScan? – Jacob Oct 20 '18 at 13:25
  • Yes, it is covered by @ComponentScan and due to the debug unfortunately the method is not called. – THE Waterfall Oct 20 '18 at 13:29
  • you need add one more line in your WebApplicationInitializer, i have updated the answer. – Jacob Oct 20 '18 at 13:35
  • Can you confirm that NoHandlerFoundException is thrown? Or you can create a test controller to just throw this exception and see whether trigger your 404 handler – Jacob Oct 20 '18 at 14:32
  • 1
    Okay, if I throw NoHandlerFoundException in a test controller, then the thing works. But why doesn't it work if I just try to access non-existing page? – THE Waterfall Oct 20 '18 at 17:00
0

Well, as @MarkA.Fitzgerald mentioned in the comments:

The community seems to feel that there is no way to do this according to stackoverflow.com/a/13450154/1840078.

So, I guess, I can live with web.xml doing such simple stuff as creating custom error pages. I find it simple and clean instead of trying to "hardcode" it in java.

THE Waterfall
  • 645
  • 6
  • 17
0

You can create a EmbeddedServletContainerCustomizer inside one of you configuration classes. Ex

@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
    return container -> {
        ErrorPage error404Page = new ErrorPage(HttpStatus.NOT_FOUND, "/exceptions/not-found.jsp");

        container.addErrorPages(error404Page);
    };
}
mad_fox
  • 3,030
  • 5
  • 31
  • 43
-1

You can create a java class and controller to it. For example ErrorController use RequestMapping there and create a jsp or thymeleaf front-end page for it.

Here is good practice https://www.baeldung.com/custom-error-page-spring-mvc just google.