ControllerAdvice conditionally handle exception

Viewed 1160

I have a controller advice that handles the exceptional behavior in my REST controller and I came across a situation when I have to conditionally process SQLIntegrityConstraintViolationException that have a certain message (the one for duplicate keys), returning a 409, letting the other ones be handled by the default handler (returning a 500 error code).

I am thinking of 2 possible ways to achieve that:

  1. Throwing a new bare-boned Exception on the else branch on my condition, so the handling is done by Spring.
  2. Explicitly calling the general exception handler (like return handleGeneralException(exception) from inside my else branch).

I there a "proper" way to pass on a fraction of exceptions of one kind in my ControllerAdvice to another handler than the "original" one?

EDIT 1: I would like to do something like this in my ControllerAdvice:

if (exception.getMessage.contains("something")) {
    // handle exception
} else {
    // pass to other handler
}
2 Answers

Have a custom exception class and then when you throw the SQLIntegrityConstraintViolationException wrap it in your custom exception classs with additional fields whatever you want to be accessible in controller advice. Handle the custom exception in your controller advice class.

@ControllerAdvice
public class CustomExceptionHandler {

    @ExceptionHandler(YourCustomException.class)
    public final ResponseEntity<ExceptionResponse> handleNotFoundException(YourCustomExceptionex,
            WebRequest request) {
        ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage(),
                request.getDescription(false), HttpStatus.NOT_ACCEPTABLE.getReasonPhrase());
        return new ResponseEntity<>(exceptionResponse, HttpStatus.CONFLICT);
    }

}

While having the try catch block to handle this exception in your code , make sure that you handle DataIntegrityViolationException instead of SQLIntegrityConstraintViolationException if you are using Spring Data JPA. So , if you are using Spring Data Jpa then :

try {
    anyRepository.save(new YourModel(..));
} catch (DataIntegrityViolationException e) {
    System.out.println("history already exist");in res
    throw New YourCustomException("additional msg if you need it ", e);
}

Below code will capture the error message of exception SQLIntegrityConstraintViolationException in ControllerAdbvice without having to handle in code

@ControllerAdvice
public class CustomGlobalExceptionHandler extends ResponseEntityExceptionHandler {
@ExceptionHandler(value = DataIntegrityViolationException.class)
public ResponseEntity<ExceptionResponse> dataIntegrityViolationExceptionHandler(Exception ex) {
ExceptionResponse response = new ExceptionResponse();
    Throwable throwable = ex.getCause();
    while (throwable != null) {
        if (throwable instanceof SQLIntegrityConstraintViolationException) {
            String errorMessage = throwable.getMessage();
            response.setErrors(new ArrayList<>(Arrays.asList(errorMessage)));
        }
        throwable = throwable.getCause();
    }       
    return new ResponseEntity<Object>(response, HttpStatus.CONFLICT);
}
}
Related