@RestControllerAdvice and @ControllerAdvice together

Andre picture Andre · Aug 11, 2017 · Viewed 10.8k times · Source

I have an Spring MVC application which has @Controller s and @RestController s. I was thinking that: When I have some Exception at my @Controller, It gonna be handled by my @ControllerAdvice and when I have some Exception at my @RestController, It gonna be handled by my @RestControllerAdvice... But now I think It's not how things should work, because my @ControllerAdvice are catching everything, even any exception that is thrown by @RestController...I do not know if this should happen. Here my code:

 @ControllerAdvice
 public class ExceptionHandlerController {

 private final String DEFAULT_ERROR_VIEW = "error/default";

  @ExceptionHandler(Exception.class)
  public ModelAndView defaultErrorHandler(HttpServletRequest req, Exception e) 
  {   
      ModelAndView mav = new ModelAndView();
      mav.addObject("exception", e);
      mav.addObject("danger", e.getMessage());
      mav.addObject("url", req.getRequestURL());
      mav.setViewName(DEFAULT_ERROR_VIEW);
      return mav;
  }
}


@RestControllerAdvice
public class ExceptionHandlerRestController {

  @ExceptionHandler(Exception.class)
  public ResponseEntity<String> defaultErrorHandler(HttpServletRequest req, Exception e) throws Exception {
      return new ResponseEntity<>(" test "+e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);        
  }    
}

Answer

Plog picture Plog · Aug 11, 2017

Yeah @RestControllerAdvice doesn't work that way. It's just a @ControllerAdvice with @ResponseBody automatically assumed. See @RestControllerAdvice vs @ControllerAdvice.

If you wanted one @ControllerAdvice to work with one controller and one to work with the other then if you put your controllers in separate packages you should be able to do this by doing:

@ControllerAdvice("my.controller1.package")

However, the whole point of @ControllerAdvice is to share common functionality of your separate @Controllers between each other so if you want them to do separate things you might be better off just putting the methods inside the @Controllers themselves.