19

I use @ExceptionHandler to handle exceptions thrown by my web app, in my case my app returns JSON response with HTTP status for error responses to the client.

However, I am trying to figure out how to handle error 404 to return a similar JSON response like with the one handled by @ExceptionHandler

Update:

I mean, when a URL that does not exist is accessed

quarks
  • 33,478
  • 73
  • 290
  • 513

5 Answers5

46

I use spring 4.0 and java configuration. My working code is:

@ControllerAdvice
public class MyExceptionController {
    @ExceptionHandler(NoHandlerFoundException.class)
    public ModelAndView handleError404(HttpServletRequest request, Exception e)   {
            ModelAndView mav = new ModelAndView("/404");
            mav.addObject("exception", e);  
            //mav.addObject("errorcode", "404");
            return mav;
    }
}

In JSP:

    <div class="http-error-container">
        <h1>HTTP Status 404 - Page Not Found</h1>
        <p class="message-text">The page you requested is not available. You might try returning to the <a href="<c:url value="/"/>">home page</a>.</p>
    </div>

For Init param config:

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
    @Override
    public void customizeRegistration(ServletRegistration.Dynamic registration) {
        registration.setInitParameter("throwExceptionIfNoHandlerFound", "true");
    }
}

Or via xml:

<servlet>
    <servlet-name>rest-dispatcher</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>throwExceptionIfNoHandlerFound</param-name>
        <param-value>true</param-value>
    </init-param>
</servlet>

See Also: Spring MVC Spring Security and Error Handling

Community
  • 1
  • 1
Md. Kamruzzaman
  • 1,895
  • 16
  • 26
  • This is the best answer, as handling everything with Spring allows you all the functionality that comes with handling the error with Java vs a static html page. – dev Dec 06 '14 at 19:09
  • Thanks for this, it seems like the right way to do things now, however, it isn't working for me. If you have the time, is there any chance you could tell me what I'm doing wrong? http://stackoverflow.com/questions/28750038/returning-json-with-spring-on-404-in-xml-free-project – S. Buda Feb 26 '15 at 21:49
  • If you have a resource handler configured and the resource can't be found then this doesn't work. Unfortunately, the ResourceHttpRequestHandler sends a 404 response instead of throwing some sort of resource exception you can catch. –  May 06 '16 at 19:22
  • If case it doesn't work [this is a solution](https://stackoverflow.com/a/44393203/548473) – Grigory Kislin Jun 06 '17 at 14:48
  • Great. For me the problem was the missing infos for the init param config. That is what is almost always missing! – M46 Jan 21 '22 at 11:48
7

With spring > 3.0 use @ResponseStatus

  @ResponseStatus(value = HttpStatus.NOT_FOUND)
  public class ResourceNotFoundException extends RuntimeException {
    ...
}

    @Controller
    public class MyController {
    @RequestMapping.....
    public void handleCall() {
        if (isFound()) {
        // do some stuff
        }
        else {
              throw new ResourceNotFoundException(); 
        }
    }
}
Yves_T
  • 1,170
  • 2
  • 10
  • 16
  • I mean, when a URL that does not exist is accessed – quarks Nov 13 '12 at 08:09
  • The 404 or Not Found error message is a HTTP standard response code indicating that the client was able to communicate with the server, but the server could not find what was requested. – Yves_T Nov 13 '12 at 08:36
  • I mean, for example this url exist: /rest/doc/1 <= this exist, however /rest/doc/1/notexist <= not exist (this is what I mean) – quarks Nov 13 '12 at 08:40
  • Ok I think you can find your answer here then http://www.stormpath.com/blog/spring-mvc-rest-exception-handling-best-practices-part-2 – Yves_T Nov 13 '12 at 08:46
4

Simplest way to find out is use the following:

@ExceptionHandler(Throwable.class)
  public String handleAnyException(Throwable ex, HttpServletRequest request) {
    return ClassUtils.getShortName(ex.getClass());
  }

If the URL is within the scope of DispatcherServlet then any 404 caused by mistyping or anything else will be caught by this method but if the URL typed is beyond the URL mapping of the DispatcherServlet then you have to either use:

<error-page>
   <exception-type>404</exception-type>
   <location>/404error.html</location>
</error-page>

or

Provide "/" mapping to your DispatcherServlet mapping URL so as to handle all the mappings for the particular server instance.

Liam
  • 2,837
  • 23
  • 36
3
public final class ResourceNotFoundException extends RuntimeException {

}


@ControllerAdvice
public class AppExceptionHandler {
    @ExceptionHandler(ResourceNotFoundException.class)
    @ResponseStatus(HttpStatus.NOT_FOUND)
    public String handleNotFound() {
        return "404";
    }
}

Just define an Exception, an ExceptionHandler, throw the Exception from your business code controller.

igonejack
  • 2,366
  • 20
  • 29
  • This worked perfectly in my Spring 4 application, and is the appropriate solution for setting status codes for Spring-native exceptions like `NoHandlerFoundException`. – Parker Feb 07 '18 at 20:29
1

You can use servlet standard way to handle 404 error. Add following code in web.xml

<error-page>
   <exception-type>404</exception-type>
   <location>/404error.html</location>
</error-page>
Fu Cheng
  • 3,385
  • 1
  • 21
  • 24