Memo API (3-2)
Create Memo
이번 포스트에서는 메모를 생성할 때 필요한 데이터의 유효성 검사와 예외 처리에 대한 기능을 구현했다.
유효성 검사
build.gradle
유효성 검사와 관련된 Annotation을 사용하기 위해 build.gradle에 아래의 의존성을 추가한다.
implementation("org.springframework.boot:spring-boot-starter-validation")
MemoController
@PostMapping
@ResponseStatus(HttpStatus.CREATED)
fun createMemo(
@ModelAttribute @Valid createMemoRequest: CreateMemoRequest,
) {
memoService.createMemo(createMemoRequest)
}
data class CreateMemoRequest(
@field:NotEmpty(message = "Title must not be empty.")
@field:Size(max = 45, message = "Title must not exceed 45 characters.")
val title: String,
@field:NotEmpty(message = "Content must not be empty.")
val content: String,
@field:Size(max = 3, message = "Up to 3 tags can be registered.")
val tags: List<String>,
@field:Size(max = 3, message = "Up to 3 files can be registered.")
val files: List<MultipartFile>
)
Controller에서 요청 데이터에 대한 유효성 검사를 하기 위해 CreateMemoRequest 앞에 @Valid를 추가했다.
@field:(???)를 통해 CreateMemoRequest의 멤버필드 각각에 대해 유효성 검사한다.
List에 @field:Size(max = 3, ~)를 설정했는데 이는 list 안에 있는 element 개수가 최대 3개라는 의미이다.
List 안에 있는 element에 대해서도 유효성 검사를 하고 싶었는데 찾지 못했다.
GeneralExceptionHandler
API에서 발생하는 예외는 모두 ExceptionHandler를 통해 처리한다.
@RestControllerAdvice
@Order(HIGHEST_PRECEDENCE)
class GeneralExceptionHandler {
private val log = KotlinLogging.logger { }
@ExceptionHandler(BindException::class, MethodArgumentNotValidException::class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
fun handleRequestValid(exception: BindException): ErrorResponse {
val builder = StringBuilder()
for (error in exception.bindingResult.fieldErrors)
builder.appendLine("[field] ${error.field} [message] ${error.defaultMessage} [rejectedValue] ${error.rejectedValue}")
log.info { builder.toString() }
return ErrorResponse(HttpStatus.BAD_REQUEST, "System-003", builder.toString())
}
}
@ModelAttribute로 받은 데이터가 유효하지 않으면 BindingException이 발생하고
@RequestBody로 받은 데이터가 유효하지 않으면 MethodArgumentNotValidException이 발생한다.
예외가 발생하면 Timestamp, HttpResponse, ErrorCode, ErrorMessage가 들어있는 ErrorResponse를 return한다.
Request
title은 빈 값, tags에 들어있는 tag의 개수는 5개로 만들어 요청하면
@ModelAttribute CreateMemoRequest의 멤버필드에 대해 validation이 실패하기 때문에 BindException이 발생한다.
BindingException이 발생하면 GeneralExceptionHandler가 해당 Exception에 대해 ErrorResponse를 return한다.
유효성 검사가 제대로 이루어진 것을 확인할 수 있다.
예외 처리
Service 로직에 대한 예외 처리는 Service 메서드에 @Transactional Annotation만 추가하면 된다.
@Transactional
fun createMemo(createMemoRequest: CreateMemoRequest) { ... }
@Transactional
fun createTags(memo: Memo, tagsFromRequest: List<String>) { ... }
@Transactional
fun createFiles(memo: Memo, filesFromRequest: List<MultipartFile>?) { ... }
서비스 로직을 실행하는 도중에 예외가 발생하면 Transaction에 의해 기존의 쿼리문이 전부 rollback된다.
Author And Source
이 문제에 관하여(Memo API (3-2)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@morningstar/Memo-3-2저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)