1
0

Spring bootで@DateTimeFormatのバリデーションで発生する例外を調査

Last updated at Posted at 2024-03-31

環境

  • Spring boot 3.2.4
  • Amazon Corretto JDK 17

調査したこと

  • Controllerで日付のパラメタを受け取るときに、バリデーションをかけたい
  • @DateTimeFormat@JsonFormat@Sizeなどの通常のバリデーションとスローされる例外が異なっていた
  • @RequestParam@RequestBodyの位置の違いでも動作が異なるため、それぞれ試してみる

結果

位置 バリデーション スローされる例外
@PathVariable @Size ConstraintViolationException
@PathVariable @DateTimeFormat MethodArgumentTypeMismatchException
@RequestParam @Size ConstraintViolationException
@RequestParam @DateTimeFormat MethodArgumentTypeMismatchException
@RequestBody @Size MethodArgumentNotValidException
@RequestBody @JsonFormat HttpMessageNotReadableException

検証する

検証用のコード

SandboxController.java
@RestController
@Validated
public class SandboxController {

    @PostMapping("/echo/{pathText}/{pathTime}")
    public ResponseEntity<EchoResponse> postEcho(
        @PathVariable(name = "pathText") @Size(min = 1, max = 10) String pathText,
        @PathVariable(name = "pathTime") @DateTimeFormat(pattern = "yyyy-MM-dd_HH:mm:ss") LocalDateTime pathTime,
        @RequestParam(name = "paramText") @Size(min = 1, max = 10) String paramText,
        @RequestParam(name = "paramTime") @DateTimeFormat(pattern = "yyyy-MM-dd_HH:mm:ss") LocalDateTime paramTime,
        @RequestBody @Validated EchoRequest request
    ){

        EchoResponse res = new EchoResponse(paramText, paramTime);
        return new ResponseEntity<EchoResponse>(res, HttpStatus.OK);
    }

}
EchoRequest.java
@Getter
public class EchoRequest {

    @Size(min = 1, max = 10)
    String bodyText;

    //Bodyでは@DateTimeFormatが効かないので、@JsonFormatを使用する
    //@DateTimeFormat(pattern = "yyyy-MM-dd_HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd_HH:mm:ss")
    LocalDateTime bodyTime;
}
EchoResponse.java
@Getter
@Setter
@AllArgsConstructor
public class EchoResponse {
    String text;
    LocalDateTime time;
}
ControllerExceptionHandler.java
@RestControllerAdvice
public class ControllerExceptionHandler {

    @ExceptionHandler(Exception.class)
    public ResponseEntity<String> handleAnyException(Exception e){
        e.printStackTrace();
        String reason = e.getClass().toString();

        return new ResponseEntity<>(reason, HttpStatus.INTERNAL_SERVER_ERROR);
    }

}

パターンに一致する場合

{
    "text": "1234567890",
    "time": "2024-12-31T00:00:00"
}

@PathVariable@Sizeが通過できなかった場合

  • ConstraintViolationException がスローされた
POST /echo/12345678901/2024-12-31_00:00:00?paramText=1234567890&paramTime=2024-12-31_00:00:00 HTTP/1.1
{
"bodyText": "1234567890",
"bodyTime": "2024-12-31_00:00:00"
}
 
HTTP/1.1 500 Internal Server Error
class jakarta.validation.ConstraintViolationException

@PathVariable@DateTimeFormatが通過できなかった場合

  • MethodArgumentTypeMismatchException がスローされた
POST /echo/1234567890/2024-12-31_00:00:0000?paramText=1234567890&paramTime=2024-12-31_00:00:00 HTTP/1.1
{
"bodyText": "1234567890",
"bodyTime": "2024-12-31_00:00:00"
}
 
HTTP/1.1 500 Internal Server Error
class org.springframework.web.method.annotation.MethodArgumentTypeMismatchException

@RequestParam@Sizeが通過できなかった場合

  • ConstraintViolationException がスローされた
POST /echo/1234567890/2024-12-31_00:00:00?paramText=12345678901&paramTime=2024-12-31_00:00:00 HTTP/1.1
{
"bodyText": "1234567890",
"bodyTime": "2024-12-31_00:00:00"
}
 
HTTP/1.1 500 Internal Server Error
class jakarta.validation.ConstraintViolationException

@RequestParam@DateTimeFormatが通過できなかった場合

  • MethodArgumentTypeMismatchException がスローされた
POST /echo/1234567890/2024-12-31_00:00:00?paramText=1234567890&paramTime=2024-12-31_00:00:0000 HTTP/1.1
{
"bodyText": "1234567890",
"bodyTime": "2024-12-31_00:00:00"
}
 
HTTP/1.1 500 Internal Server Error
class org.springframework.web.method.annotation.MethodArgumentTypeMismatchException

@RequestBody@Sizeが通過できなかった場合

  • MethodArgumentNotValidException がスローされた
POST /echo/1234567890/2024-12-31_00:00:00?paramText=1234567890&paramTime=2024-12-31_00:00:00 HTTP/1.1
{
"bodyText": "12345678901",
"bodyTime": "2024-12-31_00:00:00"
}
 
HTTP/1.1 500 Internal Server Error
class org.springframework.web.bind.MethodArgumentNotValidException

@RequestBody@DateTimeFormatが通過できなかった場合

  • HttpMessageNotReadableException がスローされた
POST /echo/1234567890/2024-12-31_00:00:00?paramText=1234567890&paramTime=2024-12-31_00:00:00 HTTP/1.1
{
"bodyText": "1234567890",
"bodyTime": "2024-12-31_00:00:0000"
}
 
HTTP/1.1 500 Internal Server Error
class org.springframework.http.converter.HttpMessageNotReadableException
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0