-
Kotlin + Spring DTO에서 NotNull 변수의 null Validation트러블 슈팅 2023. 5. 18. 15:23
📒 상황
data class FacilityReq( @NotNull val category: Category, @NotBlank val name: String )
◼ 시설 등록 요청 DTO를 위와 같이 작성하고 name 값을 넣지 않고 요청을 보내면 에러가 발생한다.
💥 기대했던 에러는 name은 null이 될 수 없다는 에러였는데, 에러 API 응답으로 설정한 값과 다른 값이 응답으로 왔다.
📒 원인
name을 NotNull 타입인 String으로 설정해서 null을 허용하지 않는 타입으로 정의했다.
이로 인해, name이 null로 채워지게 된다면 @field:NotBlank validation 로직을 타기 전에 변수에 값을 할당하는 과정에서 예외가 발생하게 되어 다음과 같은 에러가 발생한다.
💥 HttpMessageNotReadableException
📒 해결 방법
◼ Dto에서 NotNull 타입으로 Validation을 진행하고자 하면 다음과 같이 MethodArgumentNotValid 예외를 처리하는 것이 아닌 HttpMessageNotReadableException로 예외를 처리해야 한다.
🤦♂️ MissingKotlinParameterException -> Deprecated
@RestControllerAdvice class ExceptionHandler : ResponseEntityExceptionHandler() { override fun handleHttpMessageNotReadable( ex: HttpMessageNotReadableException, headers: HttpHeaders, status: HttpStatusCode, request: WebRequest ): ResponseEntity<Any>? { logger.error("[HttpMessageNotReadableException] ${ex.message}") val errorMessage = when (val cause = ex.cause) { is MissingKotlinParameterException -> "${cause.parameter.name} is null" else -> "유효하지 않은 요청입니다" } return ResponseEntity.status(ErrorCode.REQUEST_RESOURCE_NOT_VALID.httpStatus) .body(ApiResponse.error(ErrorCode.REQUEST_RESOURCE_NOT_VALID.code, errorMessage)) } }
◼ jackson-module-kotlion 2.16 부터 Deprecated 되었다.
✔ MismatchedInputException
override fun handleHttpMessageNotReadable( ex: HttpMessageNotReadableException, headers: HttpHeaders, status: HttpStatusCode, request: WebRequest ): ResponseEntity<Any>? { logger.error("[HttpMessageNotReadableException] ${ex.message}") val listOf = listOf("a", "b", "c") println(listOf.joinToString() { it.toString() }) val errorMessage = when (val cause = ex.cause) { is MismatchedInputException -> "${cause.path.joinToString() { it.fieldName }} is null" else -> "유효하지 않은 요청입니다" } return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ApiErrorResponse(errorMessage)) }
◼ 위 코드를 작성하고 다시 요청을 보내면 다음과 같이 응답 값이 처리된다.
📒 결론
◼ Kotlin에서 NotNull 타입을 사용하면서, Null에 대한 Validation을 체크하려면 Java와 같이 Validation 어노테이션을 통해서 처리하는 것이 아닌 HttpMessageNotReadableException 예외를 잡아서 처리해야 한다.
'트러블 슈팅' 카테고리의 다른 글
Jpa Validate 에러 (with. Oracle DB, h2) (0) 2023.05.30 Kotest + 생성자 Bean 주입 (0) 2023.05.27 [Junit5] JPA metamodel must not be empty! (0) 2022.11.22 [Junit5] org.mockito.exceptions.misusing.MissingMethodInvocationException (0) 2022.11.21 [Spring] Spring Security + Junit5 (0) 2022.11.15