#28 [SpringBoot/KotlinでBFF]Whitelabel-Error対応

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

存在しないURLへのリクエスト:NotFound(HttpStatus=404)を返す
ハンドリングしていないエラー(Bug):InternalServerError(HttpStatus-500)を返す

デフォルトではSpringBootが、JSONでエラーレスポンスを返すかブラウザでアクセスした場合はWhitelabel Error Pageが表示される。セキュリティの観点からもエラーハンドリング をカスタマイズするのがベター。

エラー発生時のレスポンスモデルを用意する

data class ApplicationError(
        val detailCode: String,
        val message: String
)

次にSpring公式ページを参考にErrorControllerクラスを実装する。サンプルコードが無いのでErrorControllerのクラスを確認し実装が必要なメソッドを確認して実装。

詳細コード、メッセージは別途体系化するとして、ここではひとまずの値を設定。

@RestController
@RequestMapping("/error")
class CustomErrorController : ErrorController {

    private val log = LogFactory.getLog(CustomErrorController::class.java)

    @Value("\${server.error.path:\${error.path:/error}}")
    private val errorPath: String = ""

    override fun getErrorPath(): String {
        return errorPath
    }

    @RequestMapping
    fun handleError(request: HttpServletRequest): ResponseEntity<ApplicationError> {

        val statusCode = request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE)
        if (statusCode == HttpStatus.NOT_FOUND.value()) {
            val error = ApplicationError("E1002", "Request url is incorrect.")
            return ResponseEntity<ApplicationError>(error, HttpStatus.NOT_FOUND)
        }

        log.error(request.getAttribute(RequestDispatcher.ERROR_EXCEPTION))
        val error = ApplicationError("E1003", "Unknown error was happened.")
        return ResponseEntity<ApplicationError>(error, HttpStatus.INTERNAL_SERVER_ERROR)
    }
}

結果を確認

NotFound

マッピングしていないURLにリクエストを実行して、HttpStatusが404になっている事、レスポンスモデルが意図通りのモデルであることを確認。

http://localhost:8080/tasks/12345/incorrect

InternalServerError

コードに一時的にバグを埋め込んでアクセス、HttpStatusが500になっている事、レスポンスモデルが意図通りのモデルであることを確認。

    @GetMapping("/{taskId}")
    @ResponseBody
    @ResponseStatus(HttpStatus.OK)
    fun getTask(@PathVariable("taskId") taskId: Int): Task {
        log.info("getTask is called with taskId($taskId).")
        
        // bug
        val a = 1 / 0

        return taskService.getTask(taskId)
    }

http://localhost:8080/tasks/12345

ログも意図通りに出力されている事を確認。

2021-02-11 15:26:19.347 ERROR 10065 --- [nio-8080-exec-4] c.e.b.controller.CustomErrorController   : org.springframework.web.util.NestedServletException: Request processing failed; nested exception is java.lang.ArithmeticException: / by zero

参考

SpringBoot公式 7.1.10. エラー処理

コード

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

コメントを残す

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

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