4

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
}
Daniel Pop
  • 456
  • 1
  • 6
  • 23

2 Answers2

0

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);
}
Ananthapadmanabhan
  • 5,706
  • 6
  • 22
  • 39
  • the problem is that that is a runtime exception - where could I possible handle and wrap it? there in the controller advice? I mean, I do not ever handle it in my code – Daniel Pop Aug 12 '20 at 13:26
  • Have a try catch bloc for your code and in the catch block handle `SQLIntegrityConstraintViolationException ` by rethrowing it as your custom exception class. – Ananthapadmanabhan Aug 12 '20 at 13:30
  • my question is where should I have that try-catch block. please see my edit – Daniel Pop Aug 13 '20 at 05:53
  • @AvramPop Have the try catch for the code block which is going to throw this exception at runtime. – Ananthapadmanabhan Aug 13 '20 at 05:58
0

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);
}
}
  • you probably did not understand the question... I want to do something like if(throwable.getCause().equals("somecause")) return new ResponseEntity<>; else (see my edit) – Daniel Pop Aug 13 '20 at 05:14