우테코 레벨2 API 예외처리 핸들링
예외처리 과정 중에 정리하게 된 내용이 길기 때문에 아래에 적습니다… ㅠ
ExceptionResolver 처리하기…
DefaultHandlerExceptionResolver
와ExceptionHandlerExceptionResolver
사이의 어딘가에…
문제의 발단… 분명히 405
에러가 나야할 것이 500
에러로 클라이언트에 던져진 것… 왜그런가 했더니
ExceptionHandler 에서 모두다 500으로 분기처리하는 것이었다
문제의 코드
만일 기존의 Exception 객체를 파라미터로 받는 메서드를 주석처리하면 아래와 같이 API 응답을 얻게 된다
응답 코드 자체는 원하는 것이지만 메세지가 고객에게 던져주기에는 굉장히 개발자 친화적이다…
DefaultHandlerExceptionResolver
로 발생한 에러를 ExceptionHandlerExceptionResolver
를 통해 처리할 수 없는 것일까…
힌트를 알아보기 위해… 우선 DefaultHandlerExceptionResolver
를 상속받아서 사용해보기로 하였다
우선 상속을 받는다
이곳이 response의 상태코드가
200
에서405
로 바뀌는 순간이다
DefaultHandlerExceptionResolver
의 아래 메서드로 이동한다
ResponseFacade
catalina.connector.Response
coyote.Response
문제는 위 과정을 통하게 되면 이후에 어떤 처리를 하든
앞서 실행된 DefaultHandlerExceptionResolver.doResolveException
메서드에 의해
예외 메세지가 고정되어서 나간다.
즉 코드값은 원하는대로 나가지만 전체적인 포맷이 우리가 원하던 바와 다르게 나간다..
해결아닌 해결…
결국 개발자에게 가장 금기시 되는 정성의 노가다 기법으로 해결하였다…
스택오버플로의 답변을 참고해서 아래처럼 작성해보아도… 원하는 형태의 예외메시지가 담기지는 않는다
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
...
}
마침내 해결되었습니다…
요약
ResponseEntityExceptionHandler
클래스의protected handleExceptionInternal
메서드를 상속합니다 … ㅎㅎ
에러 응답 성공
동작 원리
ResponseEntityExceptionHandler
클래스는 내부적으로 handleException
란 메서드를 가지고 있는데
이 메서드는 30개 정도 되는 분기처리에 의해 (아래 그림 참고) 어느 한 메서드를 호출하게 되고
결국 아래의 메서드를 호출합니다
이제 스프링 내부의 분기처리 때문에 핸들링해주었던 아래 코드들은 필요 없게 되었네요…ㅎㅎ
Ambiguous @ExceptionHandler method mapped
에러
ResponseEntityExceptionHandler
를 상속받을 때 발생한 에러인데
ControllerAdvice
와 ResponseEntityExceptionHandler
에서 각각 선언한 @ExceptionHandler
가 겹쳐서 발생한 에러이다.
겹치는 부분은 따로 오버라이드해서 사용하면 된다.
예를들어 MethodArgumentNotValidException
를 처리하는 부분이 그럴 수 있다
참고
참고로 저렇게 하면request
,response
객체를 받아올 수 있다…
참고 URL
스프링 기본 예외처리를 거치게 하고 싶은 경우
https://stackoverflow.com/questions/29193190/can-a-generic-exceptionhandler-and-defaulthandlerexceptionresolver-play-nice
https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-exceptionhandlers
https://docs.spring.io/spring-framework/docs/5.3.20/javadoc-api/org/springframework/web/servlet/mvc/support/DefaultHandlerExceptionResolver.html
스프링에서 제공하는 예외를 커스텀하기
https://docs.spring.io/spring-framework/docs/5.3.20/javadoc-api/org/springframework/web/servlet/mvc/method/annotation/ResponseEntityExceptionHandler.html
Ambiguous @ExceptionHandler method mapped
에러
https://stackoverflow.com/questions/51991992/getting-ambiguous-exceptionhandler-method-mapped-for-methodargumentnotvalidexce
https://velog.io/@litsynp/Getting-Ambiguous-ExceptionHandler-method-mapped-for-XXXException