티스토리 뷰

반응형

리액티브 마이크로서비스를 만들 때 어떤 오류도 정상적으로 처리해야 됩니다.

따라서 리액터 프레임워크는 이런 오류를 처리하기 위한 메커니즘을 제공합니다.

 

 

핸들러에서 오류 찾기

핸들러를 만들 때 오류가 발생할 수 있으며 이런 오류는 리액티브 게시자 onErrorResume에서 특별한 방법으로 처리 가능합니다.

 

@Component
class CustomerHandler(private val customerService: CustomerService) {
    
    ...
    
    fun create(serverRequest: ServerRequest) =
            customerService.createCustomer(serverRequest.bodyToMono()).flatMap {
                created(URI.create("/functional/customer/${it.id}")).build()
            }.onErrorResume(Exception::class) {
                badRequest().body(fromObject("400 BAD REQUEST"))
            }

}

onErrorResume을 사용해 오류가 발생하면 해당 오류를 처리할 수 있다는 것을 모든 리액티브 게시자에게 알릴 수 있습니다. 위에서는 람다식으로 코드를 작성하였습니다.

 

잘못된 Body 값을 POST로 보내면 아래와 같은 응답을 얻을 수 있습니다.

400 BAD REQUEST

 

 

Error에 대해 JSON 응답을 하는 data class를 만들었습니다.

data class ErrorResponse(
        val error: String,
        val message: String
)

 

그리고 아래와 같이 적용하였습니다.

@Component
class CustomerHandler(private val customerService: CustomerService) {
    
    ...
    
    fun create(serverRequest: ServerRequest) =
            customerService.createCustomer(serverRequest.bodyToMono()).flatMap {
                //status(HttpStatus.CREATED).body(fromObject(it))
                created(URI.create("/functional/customer/${it.id}")).build()
            }.onErrorResume(Exception::class) {
                badRequest().body(fromObject(ErrorResponse("400 BAD REQUEST", it.message ?: "error")))
            }

}

 

위와 같이 잘못된 Body 값을 POST로 보내면 아래와 같은 응답을 얻을 수 있습니다.

{
    "error": "400 BAD REQUEST",
    "message": "400 BAD_REQUEST \"Failed to read HTTP message\"; nested exception is org.springframework.core.codec.DecodingException: JSON decoding error: Unexpected character ('}' (code 125)): was expecting double-quote to start field name; nested exception is com.fasterxml.jackson.databind.JsonMappingException: Unexpected character ('}' (code 125)): was expecting double-quote to start field name\n at [Source: (io.netty.buffer.ByteBufInputStream); line: 7, column: 6] (through reference chain: com.imtae.chapter4.Customer[\"telephone\"])"
}

 

 

 

 

오류 게시

이미 생성된 고객을 또 생성하려고 하면 오류를 발생해야 됩니다.

 

아래와 같이 CustomExistException 클래스를 만들었습니다.

class CustomerExistException(override val message: String) : Exception(message)

 

그리고 ServiceImpl 클래스의 함수를 아래와 같이 수정하였습니다.

@Component
class CustomerServiceImpl : CustomerService {

    ...
    
    override fun createCustomer(customerMono: Mono<Customer>) =
            customerMono.flatMap {
                if (customers[it.id] == null) {
                    customers[it.id] = it
                    it.toMono()
                } else {
                    Mono.error(CustomerExistException("${it.id}번째 고객이 이미 있습니다."))
                }
            }
}

고객이 존재하는지 확인을 하고, 존재하지 않을 경우 저장하고 Mono로 반환합니다.

고객이 없다면 Mono.error를 통해 오류를 포함하는 Mono를 생성합니다.

 

두 번째 요청 시 아래와 같은 응답을 받습니다.

{
    "error": "400 BAD REQUEST",
    "message": "4번째 고객이 이미 있습니다."
}
반응형
댓글