Backend

[Spring Boot] FeignClient와 ExceptionHandler | FeignClient의 응답값 그대로 반환하기

연_우리 2022. 7. 29. 23:08
반응형

목차

     

     

     

     

    프로젝트를 진행하다보니 FeignClient로 다른 서비스를 호출하는 일이 생겼는데,

    자식서비스가 부모서비스에 FeignClient로 API호출 시

    부모서비스에서 Exception이 터지면 그대로 자식서비스도 예외가 발생한다.

     

    에러 응답포맷이 정해져있기 때문에 부모서비스의 에러메시지를 자식서비스에서도

    그대로 반환해주면 어떨까?! 하고 생각했다

     

     

     

     

     

    기존코드

    application.yml 

    feign 설정 부분만 가지고왔다

    ...
    
    feign:
      parent-api:
        url: http://localhost:8081
      httpclient:
        follow-redirects: true
    
    ...

     

     

    ExceptionController.java

    CustomException이 발생하면 해당 handler에서 처리하게된다

    @RestControllerAdvice
    public class ExceptionController {
    
        @ExceptionHandler(CustomException.class)
        public ResponseEntity customExceptionHandler(CustomException exception){
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(exception.getResponse());
        }
        
    }

     

     

    CustomException.java

    CustomException은 ErrorResponse객체를 받고, ExceptionHandler에서 ErrorResponse객체를 반환한다

    public class CustomException extends RuntimeException{
    
        private ErrorResponse errorResponse;
    
        public CustomException(ErrorResponse errorResponse) {
            this.errorResponse = errorResponse;
        }
    
        public ErrorResponse getResponse(){
            return errorResponse;
        }
    }

     

     

     

    ParentController.java

    /parent/hello로 접근 시 status가 true이면 200 OK로 떨어지지만

    status가 false이면 CustomException이 발생한다

    @RestController
    @RequestMapping("/parent")
    @RequiredArgsConstructor
    public class ParentController {
    
        @GetMapping("/hello")
        public ResponseEntity hello(@RequestParam Boolean status){
    
            if(status == false){
                throw new CustomException(
                        ErrorResponse.builder()
                                .cause("status")
                                .code("value_false")
                                .message("값이 false입니다.").build()
                );
            }
    
            return ResponseEntity.ok(status);
        }
    
    }

     

     

    ParentFeignClient.java

    ChildController에서 ParentController를 호출할 수 있도록 ParentFeignClient를 생성했다.

    @FeignClient(name = "PARENT-API", url = "${feign.parent-api.url}")
    public interface ParentFeignClient {
    
        @GetMapping("/parent/hello")
        public Object hello(@RequestParam Boolean status);
    }

     

     

    ChildController.java

    @RestController
    @RequestMapping("/child")
    @RequiredArgsConstructor
    public class ChildController {
    
        private final ParentFeignClient parentFeignClient;
    
        @GetMapping("/hello")
        public ResponseEntity hello(@RequestParam Boolean status){
            return ResponseEntity.ok(
                    parentFeignClient.hello(status)
            );
        }
    }

     

     

     

     

    API 호출

    /parent/hello?status=false를 요청하면 아래와 같이 응답해준다.

     

     

     

    /child/hello?status=false를 요청하면 500에러가 발생하고,

    포맷으로 맞추어둔 에러메시지가 다른 메시지들과 섞여서 보이게된다!

     

     

     

     

    목표

    child에 반환되는 저 오류메시지를 child에서도 그대로 에러포맷에 맞추어 보내주자!

     

    반응형

     

     

     

    변경코드

    ExceptionController.java

    FeignException.class 를 받는 handler를 추가해준다.

     

    FeignException은 contentUTF8() 메서드를 가지고있는데, 여기에 Parent에서 응답해준 값을 String으로 가지고있다!

    이 JSON String을 ObjectMapper로 변환해서 반환해준다

     

    또한 status()메서드로 Parent가 응답해준 상태코드를 가져올 수 있다

    @RestControllerAdvice
    @RequiredArgsConstructor
    public class ExceptionController {
    
        private final ObjectMapper objectMapper;   //🔥🔥
    
        @ExceptionHandler(CustomException.class)
        public ResponseEntity customExceptionHandler(CustomException exception){
            return ResponseEntity
                    .status(HttpStatus.BAD_REQUEST)
                    .body(exception.getResponse());
        }
        
        /**
         * FeignClient에서 발생한 예외 그대로 전달🔥🔥
         */
        @ExceptionHandler(FeignException.class)
        public ResponseEntity feignExceptionHandler(FeignException feignException) throws JsonProcessingException {
    
            String responseJson = feignException.contentUTF8();
            Map<String, String> responseMap = objectMapper.readValue(responseJson, Map.class);
    
            return ResponseEntity
                	.status(feignException.status())
                	.body(responseMap);
        }
    
    }

     

     

     

    API 호출

    다시 /child/hello?status=false로 요청해보자

     

    Parent에서 내려준 응답포맷, 상태코드를 그대로 Child에서도 반환해줄 수 있게되었다!

     

     

     

     

     

     

    반응형
    • 네이버 블러그 공유하기
    • 페이스북 공유하기
    • 트위터 공유하기
    • 구글 플러스 공유하기
    • 카카오톡 공유하기