概要
doOnError()とonErrorResume()を使用した、基本的な例外処理の方法についてまとめた。
retrieve()とexchangeToMono()の記事にて、レスポンスをもとにハンドリングする方法について紹介したが、
この記事では、上記で拾いきれない例外処理やエラーログを出力させる方法について紹介する。
前提
retrieve()とexchangeToMono()を使用してステータスハンドリングを行う方法は以下の記事で紹介している。
概要 retrieveメソッドを使用した、基本的なGET通信の使用方法についてまとめた。 今回はリクエスト送信後にエラー(4xx系や5xx系など)となった場合のハンドリング方法について紹介する。 尚、動作確認を行うための事前準備に[…]
概要 exchangeToMonoメソッドを使用した、基本的なGET通信の使用方法についてまとめた。 今回はリクエスト送信後に意図しないレスポンスを受け取った際のハンドリング方法について紹介する。 尚、動作確認を行うための事前準備[…]
基本的な使い方
doOnError()とonErrorResume()の基本的な使い方について紹介する。
実装方法
retrieve()とexchangeToMono()にて使用する方法を紹介する。
retrieve()にて使用
toEntity()やbodyToMono()の後にチェーンして使用する。
WebApiClient.java
public <T> ResponseEntity<T> getEntity(URI uri, Class<T> responseType) {
return webClient.get()
.uri(uri)
.retrieve()
.onStatus(HttpStatus::is4xxClientError, res -> {
// 4xx系ステータス
return res.bodyToMono(ApiErrorInfo.class)
.flatMap(body -> Mono.error(new ClientErrorException(body.getErrorTitle(),
body.getErrorMsg(), body.getStatus())));
})
.onStatus(HttpStatus::is5xxServerError, res -> {
// 5xx系ステータス
return res.bodyToMono(ApiErrorInfo.class)
.flatMap(body -> Mono.error(new ServerErrorException(body.getErrorMsg())));
})
.onStatus(status -> !status.is2xxSuccessful(), res -> {
// 2xx, 4xx, 5xx以外の想定外ステータス
return Mono.error(new UnknownErrorException("想定外エラー"));
})
.toEntity(responseType)
.doOnError(e -> {
logger.warn("WebClientエラー発生: {}", e.toString());
})
.onErrorResume(e -> {
if (e instanceof ClientErrorException || e instanceof ServerErrorException || e instanceof UnknownErrorException) {
return Mono.error(e);
} else {
return Mono.error(new IllegalStateException("想定外エラー", e));
}
})
.block();
}
exchangeToMono()にて使用
exchangeToMono()が返却するMonoオブジェクトにチェーンして使用する。
WebApiClient.java
public <T> ResponseEntity<T> getEntity(URI uri, Class<T> responseType) {
return webClient.get().uri(uri).exchangeToMono(res -> {
if (res.statusCode().is4xxClientError()) {
// 4xx系ステータス
return res.bodyToMono(ApiErrorInfo.class).flatMap(body -> Mono
.error(new ClientErrorException(body.getErrorTitle(), body.getErrorMsg(), body.getStatus())));
} else if (res.statusCode().is5xxServerError()) {
// 5xx系ステータス
return res.bodyToMono(ApiErrorInfo.class)
.flatMap(body -> Mono.error(new ServerErrorException(body.getErrorMsg())));
} else if (!res.statusCode().is2xxSuccessful()) {
// 2xx, 4xx, 5xx以外の想定外ステータス
return Mono.error(new UnknownErrorException("想定外エラー"));
}
// 2xx系の処理
return res.toEntity(responseType);
})
.doOnError(e -> {
logger.warn("WebClientエラー発生: {}", e.toString());
})
.onErrorResume(e -> {
if (e instanceof ClientErrorException || e instanceof ServerErrorException || e instanceof UnknownErrorException) {
return Mono.error(e);
} else {
return Mono.error(new IllegalStateException("想定外エラー", e));
}
})
.block();
}
補足
追加したdoOnError()とonErrorResume()について補足する。
.doOnError(e -> {
logger.warn("WebClientエラー発生: {}", e.toString());
})
doOnErrorメソッド内にて例外クラスを取得し、ログ出力している。
※特に代替処理をするわけでもなく、例外が発生したら捕捉してエラーログを出力するだけ
.onErrorResume(e -> {
if (e instanceof ClientErrorException || e instanceof ServerErrorException || e instanceof UnknownErrorException) {
return Mono.error(e);
} else {
return Mono.error(new IllegalStateException("想定外エラー", e));
}
})
onErrorResumeメソッド内にてHTTP通信時の例外クラスを捕捉し、
対象の例外(ClientErrorEx、ServerErrorEx、UnknownErrorEx)の場合はそのままMonoを返却する。
上記の例外以外の場合、IllegalStateExにラップしたMonoを返却する。
これにより、WebClientのHTTP通信時に発生し得る、すべてのThrowable及びそのサブクラスの例外をハンドリングすることができる。
まとめ
☑ doOnError()は、エラー発生時にログ出力などの副作用処理を行いたい場合に使用する
☑ onErrorResume()を使うことで、発生した例外を捕捉して代替の処理を返すことができる
☑ onErrorResume()にて捕捉できる例外は、Throwable及びそのサブクラスとなる