ControllerAdvice como tratar Exception em spring boot e kotlin
O @ControllerAdvice no Spring Boot serve para centralizar o tratamento de exceções da aplicação. Em vez de colocar try/catch em todos os controllers e services, você lança uma exceção e o Spring encaminha automaticamente para a classe anotada com @ControllerAdvice.
Primeiramente vamos configurar o application.yml para não exibir dados com valores null na saída da resposta http, veja a opção jackson:
spring:
application:
name: demo
jpa:
hibernate:
ddl-auto: update
datasource:
url: jdbc:mysql://localhost:3306/mercadolivro?createDatabaseIfNotExist=true
username: root
password: root
jackson:
default-property-inclusion: non_nullCriando exceções customizadas
NotFoundException:
class NotFoundException(
override val message: String,
val errorCode: String
) : Exception()BadRequestException:
class BadRequestException(
override val message: String,
val errorCode: String
) : Exception()Criando o modelo de resposta de erro:
data class ErrorResponse(
var httpCode: Int,
var message: String?,
var internalCode: String,
var erros: List<FieldErrorResponse>?
)Nosso FieldErrorResponse:
data class FieldErrorResponse(
var message:String,
var field:String
)Nosso ENUM de erros:
enum class Errors(val code: String, val message: String) {
ML101("ML_101", "Book {%s} not exists"),
ML102("ML_102", "Cannot update book with status {%s}"),
ML201("ML_201", "Customer {%s} not exists"),
ML301("ML_301", "UUID {%s} invalid")
}Nosso controller advice para tratar os erros:
@ControllerAdvice
class ControllerAdvice {
@ExceptionHandler(NotFoundException::class)
fun handlerNotFoundExpection(ex:NotFoundException,request:WebRequest):ResponseEntity<ErrorResponse>{
val erro = ErrorResponse(
httpCode = HttpStatus.NOT_FOUND.value(),
message = ex.message,
internalCode = ex.errorCode,
erros = null
)
return ResponseEntity(erro, HttpStatus.NOT_FOUND)
}
@ExceptionHandler(BadResquetExpection::class)
fun handlerBadRequestException(ex:BadResquetExpection,request:WebRequest):ResponseEntity<ErrorResponse>{
val erro = ErrorResponse(
httpCode = HttpStatus.BAD_REQUEST.value(),
message = ex.message,
internalCode = ex.errorCode,
erros = null
)
return ResponseEntity(erro, HttpStatus.BAD_REQUEST)
}
@ExceptionHandler(MethodArgumentTypeMismatchException::class)
fun handleArgumentTypeMismatch(
ex: MethodArgumentTypeMismatchException
): ResponseEntity<ErrorResponse> {
val valorInvalido = ex.value?.toString() ?: ""
val error = ErrorResponse(
httpCode = HttpStatus.BAD_REQUEST.value(),
message = Errors.ML301.message.format(valorInvalido),
internalCode = Errors.ML301.code,
erros = null
)
return ResponseEntity(error, HttpStatus.BAD_REQUEST)
}
}Chamando o NotFound:
repository.findById(id.toString()).orElseThrow{
NotFoundException(Errors.ML101.message.format(id),Errors.ML101.code)
}A chamada do BadRequest seria similar mas com a classe de BadRequestException. No caso UUID inválido ele já pega o erro automaticamente.
Exemplos UUID:
GET http://localhost:8080/book/2618f213-233e-405f-9216-da4496be0d1erSaída:
{
"httpCode": 400,
"message": "UUID {2618f213-233e-405f-9216-da4496be0d1er} invalid",
"internalCode": "ML_301"
}Exemplo NotFound:
GET ttp://localhost:8080/book/2618f213-233e-405f-9216-da4496be0d1Saída:
{
"httpCode": 404,
"message": "Book {2618f213-233e-405f-9216-0da4496be0d1} not exists",
"internalCode": "ML_101"
}
0 comentários