简体   繁体   中英

Spring @ExceptionHandler does not return content unless body is empty

I'm using Spring @ControllerAdvice to handle exceptions

@ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {


    @ExceptionHandler(value = { DataIntegrityViolationException.class})
    @ResponseBody
    public ResponseEntity<String> unknownException(Exception ex, WebRequest req) {
        return new ResponseEntity<>(ex.getCause().getMessage(), new HttpHeaders(), HttpStatus.INTERNAL_SERVER_ERROR);

    }

The problem i'm experiencing is that when the exception occurs (when i send a request via swagger), i do not get an expected exception message, but :

{"error": "no response from server"}
Response Code : 0
Response Body : No Content

I can clearly see in debug mode that the method annotated by @ExceptionHandler is called.

I've experimented with method return types, @ResponseBody , @ResponseStatus annotations and a few other thing that came to mind, but it seems that i only get some non-empty response when i return a ResponseEntity without a body, eg

 ResponseEntity.noContent().build()

or

ResponseEntity.ok().build()

In such cases i get correct http code and a few headers

Please advise on what i'm doing wrong

  • Spring version 4.3.9
  • Spring boot version 1.5.4

Thank you in advance

UPD

I carried on experimenting and this is the solution that worked for me. It is quite close to one of the answers - i will mark that one as accepted

In short, i just created my own dto class , populated the instance with the exception details i was interested in and returned it directly My code

@ExceptionHandler(value = { DataIntegrityViolationException.class})
@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody
public ExceptionDetailHolder unknownException(Exception ex, WebRequest req) {
    final Throwable cause = ex.getCause();
    return new ExceptionDetailHolder("Error interacting with the database server",
                                     cause.getClass() + ":" + cause.getMessage(),
                                     cause.getCause().getClass() + ":" + cause.getCause().getMessage()
                                    );
}

@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
private class ExceptionDetailHolder {
    private String message;
    private String exceptionMessage;
    private String innerExceptionMessage;
}

Results (which also show the contents of ex.getMessage and ex.getCause().getMessage() as asked by commenters) :

{
  "message": "Error interacting with the database server",
  "exceptionMessage": "class org.hibernate.exception.ConstraintViolationException:could not execute statement",
  "innerExceptionMessage": "class com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:Column 'allow_copay_payments' cannot be null"
}

My way of handling exception is like below, I find the specific exception and then create my own class object ValidationErrorDTO in this case, then populate required fields in that class (ValidationErrorDTO):

@ExceptionHandler(HttpMessageNotReadableException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ResponseBody
    public ResponseEntity<ValidationErrorDTO> processValidationIllegalError(HttpMessageNotReadableException ex,
            HandlerMethod handlerMethod, WebRequest webRequest) {

        Throwable throwable = ex.getMostSpecificCause();
        ValidationErrorDTO errorDTO = new ValidationErrorDTO();
        if (throwable instanceof EnumValidationException) {

            EnumValidationException exception = (EnumValidationException) ex.getMostSpecificCause();

            errorDTO.setEnumName(exception.getEnumName());
            errorDTO.setEnumValue(exception.getEnumValue());
            errorDTO.setErrorMessage(exception.getEnumValue() + " is an invalid " + exception.getEnumName());
        }

        return new ResponseEntity<ValidationErrorDTO>(errorDTO, HttpStatus.BAD_REQUEST);
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM