I am using RestControllerAdvice to return custom responses dependending on the type of exception that happened (they are all runtime exceptions), this was the first time that I used it today and it was a very weird experience because at testing with postman and local it worked perfectly, but when we deployed to Quality it just did not work, everytime when there was an exception, the frontend did not even get any response, but in postman it kept working when making the exact request, so after like 5 hours of trying different things I tried removing the @ResponseStatus annotation and then it started responding properly to the frontend when exceptions happened, maybe I missed something about this annotation, here is the code of my RestControllerAdvice that does not work properly (when call from frontend):
@RestControllerAdvice
public class SftpExceptionHandler {
@ExceptionHandler(FileTypeNotFoundException.class)
@ResponseStatus(HttpStatus.NOT_FOUND)
public GeneralResponse handlerRequestException(FileTypeNotFoundException ex) {
return new GeneralResponse(HttpStatus.NOT_FOUND, ex.getMessage());
}
@ExceptionHandler(IncorrectConsecutiveException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public GeneralResponse handlerRequestException(IncorrectConsecutiveException ex) {
return new GeneralResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
}
@ExceptionHandler(InvalidBinaryFileException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public GeneralResponse handlerRequestException(InvalidBinaryFileException ex) {
return new GeneralResponse(HttpStatus.BAD_REQUEST, ex.getMessage());
}
}
Any idea why ResponseStatus annotation makes it fail? If I remove it then the frontend starts being able to read the response properly like the postman
Example of one of my custom exceptions:
public class InvalidBinaryFileException extends RuntimeException {
private static final long serialVersionUID = 1L;
public InvalidBinaryFileException(String message) {
super(message);
}
}
CodePudding user response:
After analyzing very carefully everything, @ResponseStatus
is not the problem, it is doing what it is ment to be, but I am going to explain what is going on and leave this here in case somebody else comes through this because it can be tricky if you use it for the first time:
@RestControllerAdvice
public class SftpExceptionHandler {
@ExceptionHandler(IncorrectConsecutiveException.class)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public GeneralResponse handlerRequestException(IncorrectConsecutiveException ex) {
return new GeneralResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
}
}
So as you can see I set the @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
as internal server error which means error 500, but okay below in my code I am also setting an status and a message here new GeneralResponse(HttpStatus.INTERNAL_SERVER_ERROR, ex.getMessage());
So making the request through Postman, while USING @ResponseStatus
it appears like this:
notice the response status in the upper right is 500 Internal Server Error
, and also in my custom response it is "code":500
.
Now notice how the response from the same request will look WITHOUT @ResponseStatus
at the same code you saw above:
By this point you can already see whats the difference, without the @ResponseStatus we get a 200 as a status, but my custom response (GeneralResponse) object is still giving the same response as before with "code":500
, so what is the conclusion?
Conclusion:
The frontend is expecting always a 200 as the response status, so after that it can evaluate the internal code of the GeneralResponse object, so the problem is not @ResponseStatus
, it is actually the frontend needs to update, so it can also read what is inside response objects with 500 as status or so, hope this helps!