반응형
이전 WebClient 글 예제 코드로 아래와 같이 clientResponse.createException().flatMap() 과 onErrorResume 을 사용했는데 flatMap 을 해서 다시 Mono.error 로 감싸는, 어떻게 보면 비효율적인 코드다.
AS-IS
.retrieve()
.onStatus(
httpStatus -> httpStatus != HttpStatus.OK,
clientResponse -> {
return clientResponse.createException()
.flatMap(it -> Mono.error(new RuntimeException("code : " + clientResponse.statusCode())));
})
.bodyToMono(String.class)
.onErrorResume(throwable -> {
return Mono.error(new RuntimeException(throwable));
});
그래서 아래와 같이 flatMap 은 map으로, onErrorResume 은 onErrorMap 으로 바꿔서 Mono.error 로 wrapping 한거를 없앨 수 있다.
TO-BE
.retrieve()
.onStatus(
httpStatus -> httpStatus != HttpStatus.OK,
clientResponse -> {
return clientResponse.createException()
.map(it -> new RuntimeException("code : " + clientResponse.statusCode()));
})
.bodyToMono(String.class)
.onErrorMap(throwable -> {
return new RuntimeException(throwable);
});
그런데 주의할점이 있다. exchangeToMono나 exchangeToFlux 메서드에서는 flatMap을 유지해야 한다. 아래 코드와 같이 map으로 하게 되면 리턴타입이 Mono<RuntimeException> 이 되고 정상적인 리턴타입인 Mono<String> 과 안맞아 컴파일 에러가 발생한다.
.exchangeToMono(clientResponse -> {
if (clientResponse.rawStatusCode() == HttpStatus.BAD_REQUEST.value()) {
// Mono<RuntimeException> type. 이걸 리턴하면 컴파일 에러발생
clientResponse
.createException()
.map(it -> new RuntimeException("400!!"));
// Mono<String> type
return clientResponse
.createException()
.flatMap(it -> Mono.error(new RuntimeException("400!!")));
}
if (clientResponse.rawStatusCode() == HttpStatus.INTERNAL_SERVER_ERROR.value()) {
return clientResponse
.createException()
.flatMap(it -> Mono.error(new RuntimeException("500!!")));
}
// Mono<String> type
return clientResponse.bodyToMono(String.class);
})
cf) Mono.error 는 원본 T 타입을 유지시키므로 Mono<String> 리턴타입이 나온다.
public static <T> Mono<T> error(Throwable error) {
return onAssembly(new MonoError(error));
}
마지막으로 onErrorMap은 아래 코드와 같이 활용하는것도 가능하다. WebClient 요청이 Timeout 으로 실패했을 때만 retry 를 수행하는데 3번다 실패하면 RetryExhaustedException 이 발생한다. 그래서 RetryExhaustedException 일때만 getCause(한꺼풀 벗겨내서) 를 뒤로 전달한다.
.retryWhen(
Retry
.fixedDelay(3, Duration.ofMillis(500))
.filter(YBSUtils::isTimeoutError)
)
.onErrorMap(
Exceptions::isRetryExhausted,
Throwable::getCause
)
...
반응형
'Spring' 카테고리의 다른 글
json error stack trace print 여부 커스텀 프로퍼티 (0) | 2021.11.22 |
---|---|
WebClient 사용할때 주의 (5편) (0) | 2021.11.11 |
여러 API 결과 조합(with 비동기) (0) | 2021.10.31 |
jackson-dataformat-xml 이슈 정리 (0) | 2021.10.19 |
@RequestParam 사용 시 Null에 대한 고민 정리 (0) | 2021.09.20 |