アプリ全体の共通エラーハンドリングを実装する。
外部APIアクセス時にReadTimeout/ConnectTimeoutが発生した時の共通処理としてInternalServerError(HttpStatus-500)を返す様にエラーハンドリングする。
エラー発生時のレスポンスモデルを用意する
data class ApplicationError(
val detailCode: String,
val message: String
)
次にSpring公式ページのサンプルを参考にResponseEntityExceptionHandlerを継承したエラーハンドリング クラスを作り上記のエラーレスポンスモデルに情報を設定する。
詳細コード、メッセージは別途体系化するとして、ここではひとまずの値を設定。
ログにexceptionのメッセージを出力し解析できるようにしておく。
@RestControllerAdvice
class GlobalExceptionHandler : ResponseEntityExceptionHandler() {
private val log = LogFactory.getLog(GlobalExceptionHandler::class.java)
@ExceptionHandler(ResourceAccessException::class)
@ResponseBody
fun handleResourceAccessException(request: HttpServletRequest, ex: ResourceAccessException): ResponseEntity<ApplicationError> {
log.error(ex.message)
val error = ApplicationError("E1001", "Network error was happened.")
val status = getStatus(request)
return ResponseEntity<ApplicationError>(error, status)
}
private fun getStatus(request: HttpServletRequest): HttpStatus {
val statusCode: Int? = request.getAttribute("javax.servlet.error.status_code") as Int?
if (statusCode == null) {
return HttpStatus.INTERNAL_SERVER_ERROR
}
return HttpStatus.valueOf(statusCode)
}
}
結果を確認
ReadTimeout/ConnectTimeoutを意図的に発生させてHttpStatusが500になっている事、レスポンスモデルが意図通りのモデルであることを確認。
http://localhost:8080/tasks/12345
ログも意図通りに出力されている事を確認。
2021-02-08 07:35:59.674 ERROR 5034 --- [nio-8080-exec-2] c.e.b.controller.GlobalExceptionHandler : I/O error on GET request for "http://localhost:50000/tasks/12345": Read timed out; nested exception is java.net.SocketTimeoutException: Read timed out
コメントを残す