Development/Spring

[Spring] Spring exception handler 추가 - ambiguous handler

hyelie 2022. 10. 5. 10:33

기존에는 아래와 같이 ResponseEntityExceptionHandler를 상속받아서 handling 했었다.

@Slf4j
@RestControllerAdvice
public class GlobalExceptionHander extends ResponseEntityExceptionHandler {

    // 입력 정보가 다를 때
    // sql에 중복되어 있을 때

    @ExceptionHandler(value = {DataIntegrityViolationException.class})
    protected ResponseEntity<ErrorResponse> handleIntegrityViolateException(){
        log.error("handleDataException throws Exceptions : {}", ErrorCode.PARAMETER_NOT_VALID);
        return ErrorResponse.toResponseEntity(ErrorCode.PARAMETER_NOT_VALID);
    }

    @ExceptionHandler(value = {CustomException.class})
    protected ResponseEntity<ErrorResponse> handleCustomException(CustomException e){
        log.error("custom exception throws Exceptions : {}", e.getErrorCode().getMsg());
        return ErrorResponse.toResponseEntity(e.getErrorCode());
    }

    @ExceptionHandler(value = {SignatureException.class})
    protected ResponseEntity<ErrorResponse> handleSignatureException(){
        log.error("SignatureException throws Exceptions : {}", ErrorCode.INVALID_REFRESH_TOKEN);
        return ErrorResponse.toResponseEntity(ErrorCode.INVALID_ACCESS_TOKEN);
    }

    @ExceptionHandler(value = {JDBCConnectionException.class})
    protected ResponseEntity<ErrorResponse> handleDBConnectionException(){
        log.error("handleDBConnectionException throws Exceptions : {}", ErrorCode.DATABASE_CONNECTION_ERROR);
        return ErrorResponse.toResponseEntity(ErrorCode.DATABASE_CONNECTION_ERROR);
    }

    @ExceptionHandler(value = {RedisConnectionException.class})
    protected ResponseEntity<ErrorResponse> handleRedisConnectionException(){
        log.error("handleDBConnectionException throws Exceptions : {}", ErrorCode.REDIS_CONNECTION_ERROR);
        return ErrorResponse.toResponseEntity(ErrorCode.REDIS_CONNECTION_ERROR);
    }
}

 

그런데 이걸 하는 도중 문제가 생겼는데, HttpMessageNotReadableException(Json파일이 비었을 때), HttpMediaTypeNotSupportedException(Form에서 보내는 media type이 다른 경우), HttpRequestMethodNotSupportedException(GET에 대한 요청 api만 만들었는데 POST에 대한 요청이 오는 경우, 즉 만들지 않은 요청이 오는 경우), MissingPathVariableException(Pathvariable이 없는 경우)에 대해서 위와 같이

 

@ExceptionHandler(value = {HttpMediaTypeNotSupportedException.class})
    protected ResponseEntity<ErrorResponse> handleException(){
        ...
    }

 

이렇게 짜면 ambiguous하다는 에러가 나왔다. 일반적으로 ambiguous하다면 모호한 경우, 즉 함수가 중복된 경우가 있다는 것이다. 그래서 찾아보니 나는 ResponseEntityExceptionHandler를 extend해서 사용했는데, ResponseEntityExceptionHandler 안에 이미 위에 대한 것들이 구현되어 있었다.

 

https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.html

 

위 링크에 보면 함수가 나와있다.

 

그래서 각각 함수들을 overriding해서 내가 원하는 대로 고쳐야 했다.

 

    @Override
    protected ResponseEntity<Object> handleHttpMessageNotReadable(
        HttpMessageNotReadableException ex, HttpHeaders headers, HttpStatus status, WebRequest request){
            log.error("handleHttpMessageNotReadable throws Exceptions : {}", ErrorCode.PARAMETER_NOT_VALID);
            JSONObject json = ErrorResponse.toJson(ErrorCode.PARAMETER_NOT_VALID);
            return new ResponseEntity<Object>(json.toString(), HttpStatus.BAD_REQUEST);
        }

    @Override
    protected ResponseEntity<Object> handleHttpMediaTypeNotSupported(
            HttpMediaTypeNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request){
        log.error("handleHttpMediaTypeNotSupported throws Exceptions : {}", ErrorCode.UNSUPPORTED_MEDIA_TYPE);
        JSONObject json = ErrorResponse.toJson(ErrorCode.UNSUPPORTED_MEDIA_TYPE);
        return new ResponseEntity<Object>(json.toString(), HttpStatus.UNSUPPORTED_MEDIA_TYPE);
    }

    @Override
    protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(
            HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request){
        log.error("handleHttpRequestMethodNotSupported throws Exceptions : {}", ErrorCode.METHOD_NOT_ALLOWED);
        JSONObject json = ErrorResponse.toJson(ErrorCode.METHOD_NOT_ALLOWED);
        return new ResponseEntity<Object>(json.toString(), HttpStatus.METHOD_NOT_ALLOWED);

    }

    @Override
    protected ResponseEntity<Object> handleMissingPathVariable(
        MissingPathVariableException ex, HttpHeaders headers, HttpStatus status, WebRequest request){
            log.error("handleMissingPathVariable throws Exceptions : {}", ErrorCode.MISSING_PARAMETER);
            JSONObject json = ErrorResponse.toJson(ErrorCode.MISSING_PARAMETER);
            return new ResponseEntity<Object>(json.toString(), HttpStatus.BAD_REQUEST);
        }

 

이런 식으로 고쳤다.