#27 [SpringBoot/KotlinでBFF]サーバーエラー処理-共通-ネットワークエラー

アプリ全体の共通エラーハンドリングを実装する。

外部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

参考

SpringBoot公式 7.1.10. エラー処理

コード

https://github.com/little-engineer/bff-sample/pull/34/files

コメントを残す

メールアドレスが公開されることはありません。

ABOUT US
little
15年以上プログラマーをしているエンジニアです。Kotlin, Java, Python, C++を使用したServerSideの開発に携わってきました。とりあえずやってみるスタイルで記事を更新していきます。