400 BadRequestの時の困りごと
SpringBootでcommons-validatorのチェックを共通化してみようでcommons-validatorのチェックを共通化しましたが、これで入力チェックで異常値だとResponseに
{
"errors": {
"body": [
"〇〇は〇〇です", "△△は△△です"
]
}
}
が返るようになってめでたし、めでたしでしたが、ひとつ問題が、
このcommons-validatorのチェックはSpringのcontrollerがリクエストを受け取って、型に変換できてから動き出します。そもそもリクエストがぶっ壊れていて、型に変換できない場合、commons-validatorのチェックは全く動きません。
その典型的な例がこれです
@RequestParam("serialNo") serialNo: String
kotlinにはnull許容型、null非許容型があります。上の例ではnull非許容型です。
この状態でRequestのJSONでserialNoがnullだったら、もしくはserialNoのタグ自体が無い場合、Springのcontrollerはリクエストを型に変換できません。
型に変換できないので、当然、commons-validatorも動きません。
Responseには、
{
"timestamp" : "20XX-XX-XX XX:XX:XX",
"status" : 400,
"error" : "Bad Request",
"message" : ""
"path" : "http://www.sun-m.co.jp/sample/xxx"
}
と言う・・・受け取ってもなんの意味もない、ありがたくないResponseが返ります。
何よりも、commons-validatorが動いて入力値異常の時と、そのはるか手前でspringのcontrollerが弾いた時とResponseの形が違うのは、フロント側にとっても困りものです。(最低でも型は同じにしてほしい)
で、前回のValidationExceptionHandleControllerにメソッドをもう1個追加します
@RestControllerAdvice
class ValidationExceptionHandleController {
companion object {
const val UNEXPECTED_ERROR_MESSAGE = "予期せぬエラーが発生しました。保守窓口にお問い合わせ下さい"
}
・・・
@ExceptionHandler(HttpMessageNotReadableException::class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
fun handleHttpMessageNotReadableException(ex: HttpMessageNotReadableException): ResponseEntity<ValidationError> {
return ResponseEntity(
ValidationError(
errors = ValidationErrors(body = listOf(UNEXPECTED_ERROR_MESSAGE))
),
HttpStatus.BAD_REQUEST
)
}
}
これで型てきには同じResponseが返ります
{
"errors": {
"body": [
"予期せぬエラーが発生しました。保守窓口にお問い合わせ下さい"
]
}
}