ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • NumberFormatException
    운영 중인 서비스/Coconut. 2024. 1. 23. 15:30

     

    게시글 조회하기 api 작성하면서 테스트 케이스를 적던 중에 만난 이슈입니다.

    결론은 NumberFormatException 은 IllegalArgumentException을 상속하고 있다. 입니다 ㅎㅎ

     

     


     

     

    게시글 상세를 가져오는 서비스 코드 입니다.

    만약 id가 숫자로 변환이 불가능한 문자열이 들어오는 케이스를 대응하려고 하고 있었습니다.

      @Override
      public PostResDto getPost(String id) {
        int postId = Integer.parseInt(id);
        
        PostResDto dto = new PostResDto(1, "t","t","t","2",1, LocalDateTime.now());
        return dto;
      }

     

     

    500이 응답으로 올걸 예상하고 포스트맨으로 id에 a를 넣어서 요청을 보냈는데, 400이 응답으로 옵니다.

     

     

     

    이상해서 parseInt의 인터페이스를 확인하여보니 NumberFormatException을 예외로 던진다고 나와있습니다.

     

     

    제가 작성한 글로벌 RestControllerAdvice에는 NumberFormatException을 핸들링하고 있지 않기 때문에 더 당황스러웠습니다.

    @Slf4j
    @RestControllerAdvice
    public class GlobalExceptionHandler {
    
      @ResponseStatus(BAD_REQUEST)
      @ExceptionHandler(InvalidDataAccessApiUsageException.class)
      public @ResponseBody HttpErrorInfo handleInvalidDataAccessApiUsageException(WebRequest req, InvalidDataAccessApiUsageException ex) {
        return createHttpErrorInfo(BAD_REQUEST, req, ex);
      }
    
      @ResponseStatus(BAD_REQUEST)
      @ExceptionHandler(IllegalArgumentException.class)
      public @ResponseBody HttpErrorInfo handleIllegalArgumentException(WebRequest req, IllegalArgumentException ex) {
        return createHttpErrorInfo(BAD_REQUEST, req, ex);
      }
    
      @ResponseStatus(BAD_REQUEST)
      @ExceptionHandler(MethodArgumentNotValidException.class)
      public @ResponseBody HttpErrorInfo handleInvalidInputException(WebRequest req, MethodArgumentNotValidException ex) {
        return createHttpErrorInfo(BAD_REQUEST, req, ex);
      }
    
      @ResponseStatus(INTERNAL_SERVER_ERROR)
      @ExceptionHandler(Exception.class)
      public HttpErrorInfo handleAllException(WebRequest req, Exception ex) {
        return createHttpErrorInfo(INTERNAL_SERVER_ERROR, req, ex);
      }
    
      private HttpErrorInfo createHttpErrorInfo(HttpStatus httpStatus, WebRequest req, Exception ex) {
        final String path = req.getDescription(false).replace("uri=", "");;
        final String message = ex.getMessage();
    
        log.debug("Returning HTTP status: {} for path: {}, message: {}", httpStatus, path, message);
        return new HttpErrorInfo(httpStatus, path, message);
      }
    }

     

     

    혹시 하여 실제로 반환되는 예외도 한번 찍어봅니다.

      @Override
      public PostResDto getPost(String id) {
        try {
          int test = Integer.parseInt(id);
        } catch (Exception ex) {
          log.info(ex.getClass().getName());
        }
    
        PostResDto dto = new PostResDto(1, "t","t","t","2",1, LocalDateTime.now());
        return dto;
      }

     

     

    문서에 적혀있는대로 NumberFormatException을 던져주고 있습니다.

     

     

    예외 핸들러를 하나씩 주석처리해보면서 확인한 결과 IllegalArgumentException에서 잡히는 걸 확인했습니다.

      @ResponseStatus(BAD_REQUEST)
      @ExceptionHandler(IllegalArgumentException.class)
      public @ResponseBody HttpErrorInfo handleIllegalArgumentException(WebRequest req, IllegalArgumentException ex) {
        return createHttpErrorInfo(BAD_REQUEST, req, ex);
      }

     

     

    마지막으로 NumberFormatException을 찾아가봤습니다.

    이 예외가 IllegalArgumentException을 상속하고 있는 것을 알 수 있습니다.

     

     

    NumberFortmatException은 별도로 핸들링하지 않는 것으로 결정을 하였습니다~

    나중에 더 자세하게 예외 케이스를 알려줘야되면 그 때 추가를 고려해보겠습니다.

     

    업캐스팅 된 데이터의 실제 타입을 확인하려면 아래 방법으로 가능합니다.

    data.getClass().getName()

     

Designed by Tistory.