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)