목차
프로젝트를 진행하다보니 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에서도 반환해줄 수 있게되었다!
'Backend' 카테고리의 다른 글
Server-Sent Event (SSE)란? feat Node.js (0) | 2022.09.20 |
---|---|
[SpringBoot] Apache Poi를 이용한 엑셀 다운로드 구현 (0) | 2022.08.20 |
모던 자바 인 액션 - 스트림 활용 (0) | 2022.07.16 |
모던 자바 인 액션 - Stream(스트림)이란?, 스트림특징, 내부반복/외부반복, 게으른중간연산 (0) | 2022.07.11 |
모던 자바 인 액션 - 람다표현식, 함수형인터페이스 (1) | 2022.07.10 |