• 카테고리

    질문 & 답변
  • 세부 분야

    백엔드

  • 해결 여부

    미해결

spring boot 3.0 이후 handleMethodArgumentNotValid 메소드

24.04.19 14:50 작성 조회수 62

0

안녕하세요 강사님

좋은 강의 감사드립니다.

 

스프링부트 3.0 이후부터는 오버라이딩한 handleMethodArgumentNotValid 메소드를 타지 않아 강의에서처럼 동작을 하지 않습니다.

다음과 같이 코드를 짜도 에러가 나면서 서버가 죽어버리는데 어떻게 해야 되나요?

@ExceptionHandler(BindException.class)
public final ResponseEntity<Object> handleMethodArgumentNotValidException(BindException ex) {
    ExceptionResponse exceptionResponse = new ExceptionResponse(LocalDateTime.now(), ex.getMessage()
            , ex.getBindingResult().toString()); // 클라이언트에게 상세정보 안보여주도록 false

    return new ResponseEntity<>(exceptionResponse, HttpStatus.NOT_FOUND);
}

에러 내용

Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.web.servlet.HandlerExceptionResolver]: Factory method 'handlerExceptionResolver' threw exception with message: Ambiguous @ExceptionHandler method mapped for [class org.springframework.validation.BindException]: {public final org.springframework.http.ResponseEntity com.example.myrestfulservice.exception.CustomizedResponseEntityExceptionHandler.handleMethodArgumentNotValidException(org.springframework.validation.BindException), public final org.springframework.http.ResponseEntity org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception,org.springframework.web.context.request.WebRequest) throws java.lang.Exception}
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:177) ~[spring-beans-6.1.5.jar:6.1.5]
	at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644) ~[spring-beans-6.1.5.jar:6.1.5]
	... 24 common frames omitted
Caused by: java.lang.IllegalStateException: Ambiguous @ExceptionHandler method mapped for [class org.springframework.validation.BindException]: {public final org.springframework.http.ResponseEntity com.example.myrestfulservice.exception.CustomizedResponseEntityExceptionHandler.handleMethodArgumentNotValidException(org.springframework.validation.BindException), public final org.springframework.http.ResponseEntity org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler.handleException(java.lang.Exception,org.springframework.web.context.request.WebRequest) throws java.lang.Exception}
	at org.springframework.web.method.annotation.ExceptionHandlerMethodResolver.addExceptionMapping(ExceptionHandlerMethodResolver.java:114) ~[spring-web-6.1.5.jar:6.1.5]
	at org.springframework.web.method.annotation.ExceptionHandlerMethodResolver.<init>(ExceptionHandlerMethodResolver.java:78) ~[spring-web-6.1.5.jar:6.1.5]
	at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.initExceptionHandlerAdviceCache(ExceptionHandlerExceptionResolver.java:289) ~[spring-webmvc-6.1.5.jar:6.1.5]
	at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.afterPropertiesSet(ExceptionHandlerExceptionResolver.java:256) ~[spring-webmvc-6.1.5.jar:6.1.5]
	at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.addDefaultHandlerExceptionResolvers(WebMvcConfigurationSupport.java:1063) ~[spring-webmvc-6.1.5.jar:6.1.5]
	at org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport.handlerExceptionResolver(WebMvcConfigurationSupport.java:1005) ~[spring-webmvc-6.1.5.jar:6.1.5]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
	at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.5.jar:6.1.5]
	... 25 common frames omitted

답변 2

·

답변을 작성해보세요.

0

안녕하세요, 이도원입니다.

작업하신 내용을 보면, handleMethodArgumentNotValidException 메소드에서 처리하려고 하는 예외가 BindException인데, ResponseEntityExceptionHandler 클래스에 이미 handleMethodAtgumentNotvalid 메소드의 인자로 사용되는 MethodArgumentNotValidException 가 이미 BindException을 상속 받아 구현되었기 때문에, 동일 한 두개의 핸들러가 존재하지 못한는 오류 인 것 같습니다.

아래와 같은 코드 형태라고 하면, 구현하신 handleMethodArgumentNotValidException 메소드는 삭제하시고, handleMethodAtgumentNotvalid 메소드를 재정의해서 BindException을 처리하게 해 보시면 될 것 같습니다.

@ExceptionHandler(BindException.class)
public final ResponseEntity<Object> handleMethodArgumentNotValidException(BindException ex) {
    ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(), ex.getMessage()
            , ex.getBindingResult().toString()); // 클라이언트에게 상세정보 안보여주도록 false

    return new ResponseEntity<>(exceptionResponse, HttpStatus.NOT_FOUND);
}

@Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex,
                                                              HttpHeaders headers,
                                                              HttpStatusCode status,
                                                              WebRequest request) {
    ExceptionResponse exceptionResponse = new ExceptionResponse(new Date(),
            "Validation Failed", ex.getBindingResult().toString());

    return new ResponseEntity(exceptionResponse, HttpStatus.BAD_REQUEST);
}

감사합니다.

0

인프런 AI 인턴님의 프로필

인프런 AI 인턴

2024.04.21

안녕하세요, 인프런 AI 인턴입니다.

chaelynjang님의 질문에 대해 답변드립니다.

스프링 부트 버전 3.0 이후 handleMethodArgumentNotValid 메소드의 오버라이딩이 안 되는 문제와 관련하여, 일반적으로 이 메소드는 @Valid 또는 @Validated 어노테이션이 적용된 메소드 파라미터(예: 모델 객체)의 유효성 검증에서 문제가 발견됐을 때 호출됩니다. 이를 오버라이딩하여 사용자 정의 예외 처리를 구현하는 경우입니다.

스프링 3.0 이후 에러 메시지에 따르면 Ambiguous @ExceptionHandler method mapped for [class org.springframework.validation.BindException] 즉, BindException에 대해 매핑된 @ExceptionHandler 메소드가 모호하다는 에러가 발생합니다. 여기서 문제는, 스프링이 두 메소드(handleMethodArgumentNotValidExceptionResponseEntityExceptionHandlerhandleException)를 BindException 처리용으로 인식하고 이 중 어떤 것을 사용해야 할지 결정하지 못하는 것입니다.

해결 방법으로는, @ExceptionHandler가 명시된 사용자 정의 메소드의 예외 타입을 더 구체적으로 변경하거나, 스프링의 기본 예외 처리 메커니즘을 사용하는 대신 완전히 사용자 정의 예외 처리 방식을 구현하는 것을 고려할 수 있습니다.

해당 문제 해결을 위해 추가적인 관련 정보는 제공된 내용에 포함되어 있지 않아 구체적인 코드 수정 방법을 제시하기는 어렵습니다. 하지만, 일반적으로는 @ControllerAdvice를 사용하여 애플리케이션 전반에 걸친 예외 처리를 사용자 정의하는 방식을 채택할 수 있습니다. 예를 들어, 다양한 예외에 대한 처리를 한 곳에서 관리하고, 필요에 따라 HTTP 상태 코드, 에러 메시지 등을 조정하는 방식입니다.