O Spring Framework oferece diversas formas de lidar com exceções e erros em APIs REST. Uma das abordagens mais modernas e recomendadas é o uso do ProblemDetail, que segue o padrão RFC 7807 para fornecer detalhes sobre problemas HTTP de forma estruturada e padronizada.
Neste artigo, vamos explorar como utilizar o ProblemDetail no Spring para tratar exceções e retornar respostas de erro mais informativas e padronizadas para o cliente.
O que é o ProblemDetail?
O ProblemDetail é uma classe introduzida no Spring para facilitar o tratamento de erros em APIs REST. Ele permite que você forneça informações detalhadas sobre o erro ocorrido, como o status HTTP, uma mensagem descritiva, e até mesmo propriedades adicionais, como o timestamp do erro ou a categoria do problema.
Exemplo de Uso
Vamos considerar um cenário onde estamos criando um planeta em uma API, mas o nome do planeta já existe no banco de dados. Nesse caso, uma exceção do tipo DataIntegrityViolationException será lançada, e queremos retornar uma resposta HTTP com status 409 Conflict e detalhes sobre o erro.
Teste de Integração
Primeiro, criamos um teste para garantir que, ao tentar criar um planeta com um nome já existente, a API retorne o status 409 Conflict.
@Test
@DisplayName("Create Planet with existing name return conflict")
void createPlanet_WithExistingName_ReturnConflict() throws Exception {
when(service.create(any(Planet.class))).thenThrow(DataIntegrityViolationException.class);
mockMvc.perform(post("/planets")
.content(mapper.writeValueAsString(PLANET_REQUEST))
.contentType(APPLICATION_JSON))
.andExpect(status().isConflict());
}
Tratamento da Exceção com ProblemDetail
Para capturar a exceção DataIntegrityViolationException e retornar uma resposta detalhada, utilizamos o @ExceptionHandler no Spring. O ProblemDetail nos permite fornecer informações adicionais sobre o erro, como o título, detalhes, e até mesmo propriedades personalizadas, como o StackTrace e o TimeStamp.
@ExceptionHandler(DataIntegrityViolationException.class)
public ProblemDetail handleConflict(DataIntegrityViolationException ex) {
var problemDetail = ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, ex.getLocalizedMessage());
problemDetail.setTitle("Dado informado já existe");
problemDetail.setDetail("É preciso informar um dado válido");
problemDetail.setProperty("StackTrace", ex.getStackTrace());
problemDetail.setProperty("Categoria", "API");
problemDetail.setProperty("TimeStamp", Instant.now());
return problemDetail;
}
Explicação do Código
- @ExceptionHandler(DataIntegrityViolationException.class): Este método será chamado sempre que uma exceção do tipo DataIntegrityViolationException for lançada.
- ProblemDetail.forStatusAndDetail(HttpStatus.CONFLICT, ex.getLocalizedMessage()): Cria um objeto ProblemDetail com o status HTTP 409 Conflict e a mensagem de erro da exceção.
- setTitle e setDetail: Definem o título e os detalhes do problema, que serão exibidos na resposta.
- setProperty: Adiciona propriedades personalizadas ao ProblemDetail, como o StackTrace, a categoria do erro e o timestamp do momento em que o erro ocorreu.
Resposta Esperada
Quando a exceção for lançada, a API retornará uma resposta no seguinte formato:
{
"type": "about:blank",
"title": "Dado informado já existe",
"status": 409,
"detail": "É preciso informar um dado válido",
"instance": "/planets",
"StackTrace": [...],
"Categoria": "API",
"TimeStamp": "2023-10-05T14:48:00Z"
}
Conclusão
O uso do ProblemDetail no Spring permite que você forneça respostas de erro mais detalhadas e padronizadas, melhorando a experiência do consumidor da API e facilitando a depuração. Além disso, o ProblemDetail é altamente personalizável, permitindo que você adicione informações específicas sobre o erro, como o StackTrace e o TimeStamp.
Top comments (0)