@ControllerAdviceclass GlobalExceptionHandler {
@ExceptionHandler(
ServerWebInputException::class,
HttpMessageNotReadableException::class
)
@ResponseBody fun handleHttpMessageNotReadableException(e: Exception): ResponseEntity<ErrorDTO> {
logError("Bad Request", e)
val message = when (val cause = e.cause?.findCause()) {
is InvalidFormatException -> "Can't read value '${cause.value}' for field '${cause.path.errorPath()}'"
is MissingKotlinParameterException -> "Missing required field '${cause.path.errorPath()}'"
is ServerWebInputException -> cause.reason
else -> cause?.message ?: e.message
}
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ErrorDTO(REQUIRED_PARAMETER_ABSENT, message))
}
@ExceptionHandler(
WebExchangeBindException::class
)
@ResponseBody fun handleMethodArgumentNotValidException(e: WebExchangeBindException): ResponseEntity<ErrorDTO> {
logError("Bad Request", e)
val message = e.bindingResult.allErrors.joinToString(prefix = "Validation failure. ") {
when (it) {
is FieldError -> "Field '${it.field}': ${it.defaultMessage}"
else -> it.defaultMessage.orEmpty()
}
}
return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(ErrorDTO(REQUIRED_PARAMETER_ABSENT, message))
}
@ExceptionHandler(
Error::class,
Exception::class
)
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
@ResponseBody fun internalServerError(e: Exception): ResponseEntity<ErrorDTO> {
logError("Internal server error", e)
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(ErrorDTO(INTERNAL_SERVER_ERROR_CODE, e.message))
}
companion object : Loggable
}
private const val INTERNAL_SERVER_ERROR_CODE = "INTERNAL_SERVER_ERROR"
private const val REQUIRED_PARAMETER_ABSENT = "REQUIRED_PARAMETER_ABSENT"