The new Certification Class of REST With Spring is out:


Table of Contents

1. Overview

This article will illustrate how to implement Exception Handling with Spring for a REST API. We’ll look at both the recommended solution with Spring 3.2 and 4.x but also at the older options as well.

Before Spring 3.2, the two main approaches to handling exceptions in a Spring MVC application were: HandlerExceptionResolver or the @ExceptionHandler annotation. Both of these have some clear downsides.

After 3.2 we now have the new @ControllerAdvice annotation to address the limitations of the previous two solutions.

All of these do have one thing in common – they deal with the separation of concerns very well. The app can throw exception normally to indicate a failure of some kind – exceptions which will then be handled separately.

2. Solution 1 – The Controller level @ExceptionHandler

The first solution works at the @Controller level – we will define a method to handle exceptions, and annotate that with @ExceptionHandler:

public class FooController{
    @ExceptionHandler({ CustomException1.class, CustomException2.class })
    public void handleException() {

This approach has a major drawback – the @ExceptionHandler annotated method is only active for that particular Controller, not globally for the entire application. Of course adding this to every controller makes it not well suited for a general exception handling mechanism.

The limitation is often worked around by having all Controllers extend a Base Controller class – however, this can be a problem for applications where, for whatever reasons, the Controllers cannot be made to extend from such a class. For example, the Controllers may already extend from another base class which may be in another jar or not directly modifiable, or may themselves not be directly modifiable.

Next, we’ll look at another way to solve the exception handling problem – one that is global and does not include any changes to existing artifacts such as Controllers.

3. Solution 2 – The HandlerExceptionResolver

The second solution is to define an HandlerExceptionResolver – this will resolve any exception thrown by the application. It will also allow us to implement a uniform exception handling mechanism in our REST API.

Before going for a custom resolver, let’s go over the existing implementations.

3.1. ExceptionHandlerExceptionResolver

This resolver was introduced in Spring 3.1 and is enabled by default in the DispatcherServlet. This is actually the core component of how the @ExceptionHandler mechanism presented earlier works.

3.2. DefaultHandlerExceptionResolver

This resolver was introduced in Spring 3.0 and is enabled by default in the DispatcherServlet. It is used to resolve standard Spring exceptions to their corresponding HTTP Status Codes, namely Client error – 4xx and Server error – 5xx status codes. Here is the full list of the Spring Exceptions it handles, and how these are mapped to status codes.

While it does set the Status Code of the Response properly, one limitation is that it doesn’t set anything to the body of the Response. And for a REST API – the Status Code is really not enough information to present to the Client – the response has to have a body as well, to allow the application to give additional information about the failure.

This can be solved by configuring View resolution and rendering error content through ModelAndView, but the solution is clearly not optimal – which is why a better option has been made available with Spring 3.2 – we’ll talk about that in the latter part of this article.

3.3. ResponseStatusExceptionResolver

This resolver was also introduced in Spring 3.0 and is enabled by default in the DispatcherServlet. Its main responsibility is to use the @ResponseStatus annotation available on custom exceptions and to map these exceptions to HTTP status codes.

Such a custom exception may look like:

@ResponseStatus(value = HttpStatus.NOT_FOUND)
publi class ResourceNotFoundException extends RuntimeException {
    public ResourceNotFoundException() {
    public ResourceNotFoundException(String message, Throwable cause) {
        super(message, cause);
    public ResourceNotFoundException(String message) {
    public ResourceNotFoundException(Throwable cause) {

Same as the DefaultHandlerExceptionResolver, this resolver is limited in the way it deals with the body of the response – it does map the Status Code on the response, but the body is still null.

3.4. SimpleMappingExceptionResolver and AnnotationMethodHandlerExceptionResolver

The SimpleMappingExceptionResolver has been around for quite some time – it comes out of the older Spring MVC model and is not very relevant for a REST Service. It is used to map exception class names to view names.

The AnnotationMethodHandlerExceptionResolver was introduced in Spring 3.0 to handle exceptions through the @ExceptionHandler annotation but has been deprecated by ExceptionHandlerExceptionResolver as of Spring 3.2.

3.5. Custom HandlerExceptionResolver

The combination of DefaultHandlerExceptionResolver and ResponseStatusExceptionResolver goes a long way towards providing a good error handling mechanism for a Spring RESTful Service. The downside is – as mentioned before – no control over the body of the response.

Ideally, we’d like to be able to output either JSON or XML, depending on what format the client has asked for (via the Accept header).

This alone justifies creating a new, custom exception resolver:

public class RestResponseStatusExceptionResolver extends AbstractHandlerExceptionResolver {

    protected ModelAndView doResolveException
      (HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        try {
            if (ex instanceof IllegalArgumentException) {
                return handleIllegalArgument((IllegalArgumentException) ex, response, handler);
        } catch (Exception handlerException) {
            logger.warn("Handling of [" + ex.getClass().getName() + "] 
              resulted in Exception", handlerException);
        return null;

    private ModelAndView handleIllegalArgument
      (IllegalArgumentException ex, HttpServletResponse response) throws IOException {
        String accept = request.getHeader(HttpHeaders.ACCEPT);
        return new ModelAndView();

One detail to notice here is the Request itself is available, so the application can consider the value of the Accept header sent by the client. For example, if the client asks for application/json then, in the case of an error condition, the application should still return a response body encoded with application/json.

The other important implementation detail is that a ModelAndView is returned – this is the body of the response and it will allow the application to set whatever is necessary on it.

This approach is a consistent and easily configurable mechanism for the error handling of a Spring REST Service. It does however have limitations: it’s interacting with the low-level HtttpServletResponse and it fits into the old MVC model which uses ModelAndView – so there’s still room for improvement.

4. New Solution 3 – The New @ControllerAdvice (Spring 3.2 And Above)

Spring 3.2 brings support for a global @ExceptionHandler with the new @ControllerAdvice annotation. This enables a mechanism that breaks away from the older MVC model and makes use of ResponseEntity along with the type safety and flexibility of @ExceptionHandler:

public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler(value = { IllegalArgumentException.class, IllegalStateException.class })
    protected ResponseEntity<Object> handleConflict(RuntimeException ex, WebRequest request) {
        String bodyOfResponse = "This should be application specific";
        return handleExceptionInternal(ex, bodyOfResponse, 
          new HttpHeaders(), HttpStatus.CONFLICT, request);

The new annotation allows the multiple scattered @ExceptionHandler from before to be consolidated into a single, global error handling component.

The actual mechanism is extremely simple but also very flexible:

  • it allows full control over the body of the response as well as the status code
  • it allows mapping of several exceptions to the same method, to be handled together
  • it makes good use of the newer RESTful ResposeEntity response

One thing to keep in mind here is to match the exceptions declared with @ExceptionHandler with the exception used as the argument of the method. If these don’t match, the compiler will not complain – no reason it should, and Spring will not complain either.

However, when the exception is actually thrown at runtime, the exception resolving mechanism will fail with:

java.lang.IllegalStateException: No suitable resolver for argument [0] [type=...]
HandlerMethod details: ...

5. Handle the Access Denied in Spring Security

The Access Denied occurs when an authenticated user tries to access resources that he doesn’t have enough authorities to access.

5.1. MVC – Custom Error Page

First, let’s look at the MVC style of the solution and see how to customize an error page for Access Denied:

The XML configuration:

    <intercept-url pattern="/admin/*" access="hasAnyRole('ROLE_ADMIN')"/>   
    <access-denied-handler error-page="/my-error-page" />

And the Java configuration:

protected void configure(HttpSecurity http) throws Exception {

When users try to access a resource without having enough authorities, they will be redirected to “/my-error-page“.

5.2. Custom AccessDeniedHandler

Next, let’s see how to write our custom AccessDeniedHandler:

public class CustomAccessDeniedHandler implements AccessDeniedHandler {

    public void handle
      (HttpServletRequest request, HttpServletResponse response, AccessDeniedException ex) 
      throws IOException, ServletException {

And now let’s configure it using XML Configuration:

    <intercept-url pattern="/admin/*" access="hasAnyRole('ROLE_ADMIN')"/> 
    <access-denied-handler ref="customAccessDeniedHandler" />

Or using Java Configuration:

private CustomAccessDeniedHandler accessDeniedHandler;

protected void configure(HttpSecurity http) throws Exception {

Note how – in our CustomAccessDeniedHandler, we can customize the response as we wish by redirecting or display a custom error message.

5.3. REST and Method Level Security

Finally, let’s see how to handle method level security @PreAuthorize, @PostAuthorize, and @Secure Access Denied.

We’ll, of course, use the global exception handling mechanism that we discussed earlier to handle the new AccessDeniedException as well:

public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {

    @ExceptionHandler({ AccessDeniedException.class })
    public ResponseEntity<Object> handleAccessDeniedException(Exception ex, WebRequest request) {
        return new ResponseEntity<Object>(
          "Access denied message here", new HttpHeaders(), HttpStatus.FORBIDDEN);

6. Conclusion

This tutorial discussed several ways to implement an exception handling mechanism for a REST API in Spring, starting with the older mechanism and continuing with the Spring 3.2 support and into 4.0 and 4.1.

As always, the code presented in this article is available over on Github. This is a Maven based project, so it should be easy to import and run as it is.

Go deeper into building a REST API with Spring:


  • Federico

    This has been quite helpful but I think there’s a missing piece. To write content when access is denied I had to configure the app like this:


    • These techniques are mainly security agnostic. In the case of a Spring Security enabled application, I’ll take a crack at an example soon and follow up on this thread.

      • Eric B

        @baeldung:disqus Have you had a chance to put together a Spring Security example yet for exception handling? I too have only come up with the solution presented by @Federico but would like to find something more central that I can use as a resolver as opposed to having a resolver for my MVC component and a Handler for my security component.

        • Not yet Eric – I’m planning to work on that at some point, but haven’t had to much time to write lately. I’m hopping to get to it soon. Cheers,

    • PA

      How we can do same with ??

  • for REST api’s I usually create special class called [Response] with 3 fields, isError, message, data, in other cases I write the error messages through the modelView directly into page

    usually, I don’t use generic handlers, but after reading this post I think I’ll give them a try

    • In my view – they’re not mutually exclusive – in fact, instead of the simple “This should be application specific” String, I use a very similar class – I have yet to write about it, but basically it replaces that String.
      Let me know how using the generic handler goes for you.

  • Amit Ghorpade

    I have two packages for controllers as v1 and v2 package which support version. I have controllerAdvice to support global exception handling.
    How i can apply ControllerAdvice specific to package level controllers? for example v1 controller excetions should be handled by v1ControllerAdvice and for v2 it should be by v2ControllerAdvice.

    • Amit Ghorpade

      Found the solution spring 4.0 comes with solution for package wise controlleradvice
      We can mention @ControllerAdvice(basePackages=”″) for controller which are inside in v1 package

  • Bill

    Eugen – these blogs are extremely useful! I’ve been using spring for years but have resisted bringing myself up to date. I’m impressed by the example code which actually works (not typical of blogs and posts).

    • Hey Bill – glad they’re helping. Yes – the code really should work – I’m updating it regularly. There may of course be instances where I miss something – in which case – do let me know and it will get fixed quickly. Cheers,

  • Ignacio Cañon

    Hi, first of all thank you for your blog, nice job!
    Regarding this exception-handling subject I’m not sure if I’m doing any wrong with my code, I’ve been reading your blog and other ones searching for how to handle Spring Security Exceptions, and I found several times that I could use a @ControllerAdvice to handle those exceptions, but It’s now working for me (Spring 4.2), it’s like it would only work for exceptions thrown by Controllers, despite you say It can be used for global Exceptions in the Web App.

    No Spring filter exception is handled by the moment.
    Did I miss something?

    • Hey Ignacio – glad you like the blog. First – Spring 4.2 – are you using snapshots (it’s not out yet)? Second – you might have a problem with which context your beans are defined in (if you’re using multiple contexts). The sample project has a fully working solution, so you can look at where beans are being defined and how exceptions are being thrown in there.
      Hope it helps. Cheers,

  • ChangWonSon

    I have question
    Error handling with @ControllerAdvice, Spring 4.1.1, tomcat
    almost error is caught by @ExceptionHandler
    but only 404 NOT FOUND is impossible by ExceptionHandler
    what should I do for handling 404 error

    • Hey Chang, I’m not sure I follow what you’re asking here, can you please re-phrase it? Cheers,

      • ChangWonSon

        my GlobaExceptionHaldler class use @ControllerAdvice and extends ResponseEntityExceptionHandler
        and Override two method
        1.ResponseEntityExceptionHandler.handleNoHandlerFoundException( …)
        2.ResponseEntityExceptionHandler.handleNoSuchRequestHandlingMethod( …)

        but I was not working
        if request uri is not valid (ex> localhost/uriNotExists) <- this is 404 not found
        GlobalExceptionHandler not catched exception

        • Well, it might be that the bean isn’t registered in the context; it might be that it’s registered in the wrong context or any number of other things. Not sure what the problem is from the limited info above – is there a github project I can look at? Cheers,

          • Sam

            I’ve the same problem too, so what does you mean? the bean isn’t registered in the context. Please detail it.

          • Hey Sam, as I was saying above, it’s not possible to diagnose a problem from a rough description like that. If there’s a github project you can point me to, I’d be happy to take a look. Cheers, Eugen.

        • lukasz lukasz

          Please try to add @EnableWebMvc and @EnableAutoConfiguration annotations to your configuration class. Then it works like a charm. At least for me 🙂

  • Amardeep Tanwar


    Thanks for making our REST Client happy.

    Could you please help me with a scenario where we have two operations within a controller.

    Say for example, I have a rest controller ‘ABCController’ and it has two operation like getMeOne and getMeTwo and these two operations make REST call to other independent services. These methods return response object say for example One and Two respectively. From the called Service, an exception is raised for example ResourceNotFoundException which we will handler with the help of a ResourceNotFoundExceptionHandler class annotated with controller advise.

    Since I have to send a different response object from the controller’s operations. How my handler will understand which response object has to be sent.

    • Going for the @ControllerAdvice based solution will allow you the most flexibility here. In your case – you just map the exception you know your internal logical is throwing.
      That being said – it’s important to understand here that – you will NOT be returning your One or Two DTOs in your response if you hit an exception. Basically – if you’re hitting a ResourceNotFound – you need to respond with a 404 back, along with a custom error message. So you don’t need to worry about actually returning One.

  • Valentin

    I like the @ControllerAdvice solution. Though I would like to have dynamic fields on the error response. For example if I have a custom runtime exception like CartLimitExcededException with a custom filed on it like “limit”, and I want to include this custom field in the response. Is there a way I could do this?

    • Hey Valentin – yes, you can definitely do that. The @ControllerAdvice solution allows you to fully control the body of the response. So – you have all the flexibility you need there to embed as much detail as you need in the actual exception messages your API returns back to the client. For example – with your custom exception – you need to map that exception specifically to a method and then retrieve the “limit” value from it when forming your detailed error message. Hope it helps. Cheers,


  • Karlis Zigurs

    All of these are good for handling specific exceptions, but don’t really work if you want to implement a uniform way for the controller to handle both the response body and returned error code in a uniform way (uniform format of responses is something that would be expected from any API).

    To achieve that, take a look at:

    Annotate your business logic exceptions with ResponseType (forbidden, not found, missing, etc…) and you can pick it up by resolving annotation in the exception handler easily (whether in controller or controllerAdvice).

    The only edge case that remains in this case is 404 (because it’s not thrown – just left there because there is no resolved controller to handle it) which you can handle by modifying the default exception parameters to inject any fields or messages you like (example in the same repository under /configuration)

    • Hey Karlis – using custom exceptions and annotating these is one to go. I personally prefer not to do that, and actually see this solution (keeping all of this logic in one place) as the more uniform way of doing things.
      Of course this solution works perfectly fine with custom business logic exception – and good exception does benefit a lot from semantically rich exceptions. These go into the one, main class as well.
      Thanks for the feedback though – definitely helpful.

  • Carlos Zela Bueno

    Hi $Eugen
    I’m try to follow your guideline but I have a error trying to override a spring exception with a responseBody customized.
    Mi class look as:

    class ResponseEntityBusinessExceptionHandler extends ResponseEntityExceptionHandler
    public ResponseEntity handleMyException (Throwable ex, HttpServletRequest request){
    return new ResponseEntity(
    “Any message for my exception”, new HttpHeaders(), HttpStatus.BAD_REQUEST);

    // Here all is ok. Below is the error
    protected ResponseEntity handleHttpMediaTypeNotAcceptable(
    HttpMediaTypeNotAcceptableException ex, HttpHeaders headers,
    HttpStatus status, WebRequest request) {
    return handleExceptionInternal(ex,
    “My Body for Not Acceptable, headers, status,request) ;
    I dont know why when override or handle a spring exception, the ResponseEntity returned is from Spring, like if super method was executed and my override to the handler was omited.
    Do you have any idea…why??

    Thank you

    • Grzegorz Piwowarek

      Carlos, I am not sure if I got the problem correctly. handleMyException() works correctly and below methods don’t?

      • Carlos Zela Bueno

        Grzegorz, correct..When use @ExceptionHandler for my exception classes, it’s working fine and return my response Entity. However, when I override any spring handle exception such as handleMediaTypeNotAcceptable or handleMissingPathParameter apparently I received spring response entity.
        In abstract..I take handle exception by default of spring but I want a customized response, change response body to handle Exception of spring and add a body to handle that by default doesn’t have a body.
        I hope I have been clearer now.


        • Grzegorz Piwowarek

          Ok, with such a small snippet it’s really hard to tell anything. Could you prepare a repo/PR on GitHub with the whole code to investigate?

          • Carlos Zela Bueno

            I’ve written more details in

            Put focus in RestAPIControllerAdvice.handleHttpMediaTypeNotAcceptable method.
            I’ve noted that when I sent a String body it works fine. But when I use my ResponseError bean spring send the exception. My override haven’t effect when use responseError bean, only to String message.

            Thank you in advance!

          • Grzegorz Piwowarek

            I can’t seem to reproduce the problem. Whenever I am sending the mentioned header, I simply get an empty response request does not get matched.

  • jd

    Good post. Thanks.

    How can you catch the exception generated during the JSON parsing in POST operation for instance? I’ve trying to generate my own response, unsuccessfully. Somehow that exception is caught by someone else before it gets to the generic @ControllerAdvice controller.

    • Hey JD – that’s a good question, but one I’ll only be able to answer at a high level without more details.
      So – if your exception is caught by some other piece of code, you’ll have to carefully debug and see who’s catching it. The @ControllerAdvice annotated global handler will only catch exceptions that are actually thrown by the underlying code. If an exception is already handled, naturally – it won’t be caught by the global handler.
      Hope that helps point you in the right direction.

      • jd

        Found it! You just need to do:

        protected ResponseEntity handleHttpMessageNotReadable(final HttpMessageNotReadableException exception,
        final HttpHeaders headers, final HttpStatus status, final WebRequest request) {

        ApiError apiError = new ApiError( … your constructor logic …. );

        return new ResponseEntity(apiError, apiError.getStatus());

        In your @ControllerAdvice controller.

        Thanks a lot.

        • It looks like the actual exception that was being thrown was the HttpMessageNotReadableException. Cool, I’m glad you were able to sort it out.

  • Illia Trach

    Is it OK that all exception trace is being logged and printed in to console?
    I have implemented @ControllerAdvice.

  • Igor Dmitriev

    Hi Eugen, thank you for this great article, but I am thinking about this:
    You have mentioned that body is null when you extend ResponseEntityExceptionHandler. But in your last implementation with @ControllerAdvice you still extend that class. I am wondering about it, what do you think: is it a good idea to have null body for REST API for those exceptions?? For instance I got HttpMessageNotReadableException when user sent wrong json and I didn’t see the reason in body what was wrong.

    • Hey Igor, I’m glad the article is helpful.
      Regarding this base class – it’s a good idea to extend it because it provides some good defaults. But no, most of the time it’s not a good idea to have a null body for your error responses – which is why I’m always calling handleExceptionInternal and passing in a body.
      Hope that clears things up. Cheers,