Reputation: 63
I'm having a peculiar situation with my @ControllerAdvice annotated ExceptionHandler in Spring Boot 1.5.3. It catches any exceptions default Exceptions, but if I throw a custom exception it does not fire.
The ExceptionHandler:
@ControllerAdvice
public class ResponseEntityExceptionHandler {
@ExceptionHandler({ HttpMessageNotReadableException.class })
protected ResponseEntity<ErrorModel> handleInvalidJson(RuntimeException e, WebRequest request) {
return new ResponseEntity<ErrorModel>(new ErrorModel().message("Could not parse JSON."), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler({ NumberFormatException.class })
protected ResponseEntity<ErrorModel> handleInvalidRequest(RuntimeException e, WebRequest request) {
return new ResponseEntity<ErrorModel>(new ErrorModel().message("Invalid request parameter."), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler({ CannotCreateTransactionException.class })
protected ResponseEntity<ErrorModel> handleTransactionCreationException(RuntimeException e, WebRequest request) {
return new ResponseEntity<ErrorModel>(new ErrorModel().message("Error connecting to the database, please make sure it is still available."), HttpStatus.BAD_REQUEST);
}
@ExceptionHandler({ NotFoundException.class })
protected ResponseEntity<ErrorModel> handleApiException(RuntimeException e, WebRequest request) {
return new ResponseEntity<ErrorModel>(new ErrorModel().message(e.getMessage()), HttpStatus.NOT_FOUND);
}
}
The top 3 Exceptions all get caught and handled as they are supposed to, but the bottom Exception gets handled by the default Spring-Boot ExceptionHandler. It is a custom Exception that I throw inside a Controller:
public ResponseEntity<?> deleteActor(@ApiParam(value = "Used to identify a single actor.", required = true) @PathVariable("actor_id") Integer actorId, @RequestHeader("Accept") String accept) throws Exception {
Actor actor = actorRepository.findOne(actorId);
if (actor == null) {
throw new NotFoundException(404, "Not found");
}
actorRepository.delete(actorId);
return new ResponseEntity<Void>(HttpStatus.NO_CONTENT);
}
I've tried throwing one of the top Exceptions like this:
public ResponseEntity<?> readActor(@ApiParam(value = "Used to identify a single actor.", required = true) @PathVariable("actor_id") Integer actorId, @RequestHeader("Accept") String accept) throws Exception {
Actor actor = actorRepository.findOne(actorId);
if (actor == null) {
throw new NumberFormatException("");
}
return new ResponseEntity<Actor>(actor, HttpStatus.OK);
}
and these get handled just fine...
The tomcat logs also show this:
2017-06-05 11:30:20.080 INFO 9076 --- [ main] .m.m.a.ExceptionHandlerExceptionResolver : Detected @ExceptionHandler methods in responseEntityExceptionHandler
The Exception:
public class NotFoundException extends ApiException {
private int code;
public NotFoundException (int code, String msg) {
super(code, msg);
this.code = code;
}
}
The exception inherits from this baseclass:
public class ApiException extends Exception{
private int code;
public ApiException (int code, String msg) {
super(msg);
this.code = code;
}
}
Any ideas about why the custom Exception avoids detection by the ExceptionHandler?
I would be happy to provide additional information should that be necessary.
Upvotes: 6
Views: 8195
Reputation: 21
For me the CustomException was not getting caught by @ControllerAdvice
method. I searched for hours and finally the issue got resolved on Updating the project.
Right click on your project -> Maven -> Update project
.
Upvotes: 0
Reputation: 1136
For this particular case the answer is to use Exception
instead of RuntimeException
, since NotFoundException does only inherit from Exception.
Further notable things:
To catch all exceptions one can use an @ExceptionHandler(Exception.class)
If using common names for exceptions, always check if you have imported the right one.
Upvotes: 3