Você já precisou implementar um endpoint DELETE em sua API e ficou em dúvida:

“Como evitar que o sistema quebre se o ID não existir?”
“E se esse dado estiver vinculado a outros registros no banco?”
“Como posso registrar essas ações no log?”

Neste artigo, vamos construir um exemplo completo e didático para responder tudo isso. Ideal para quem está estudando Spring Boot e quer aplicar boas práticas reais.


🚀 Objetivo

Vamos criar uma operação de deleção (exclusão) de categorias usando:

  • @DeleteMapping para mapear a rota REST
  • LOGGER para registrar o que está acontecendo
  • @ExceptionHandler para interceptar erros de forma elegante

📌 O que faz o @DeleteMapping

No mundo das APIs REST, cada ação tem um verbo HTTP:

  • GET → buscar informações
  • POST → criar algo
  • PUT → atualizar
  • DELETE → excluir

Quando usamos @DeleteMapping em um controller do Spring, estamos dizendo:

“Quando chegar uma requisição HTTP do tipo DELETE nessa rota, execute esse método.”

Exemplo no código:

@DeleteMapping(value = "/{id}")
public ResponseEntity<Void> deletarCategoria(@PathVariable Long id){
categoriaService.deletarCategoria(id);
return ResponseEntity.noContent().build();
}

Explicação linha a linha:

  • @DeleteMapping("/{id}"): diz que essa rota responde ao DELETE /categoria/5, por exemplo.
  • @PathVariable Long id: extrai o id da URL.
  • categoriaService.deletarCategoria(id): chama o método responsável por excluir a categoria.
  • ResponseEntity.noContent(): retorna o status HTTP 204 (sem conteúdo), indicando que deu tudo certo e não há nada para retornar.

📋 O que é o LOGGER e por que usá-lo

O LOGGER é usado para registrar o que acontece na aplicação enquanto ela roda.
É como um diário de bordo do sistema. Em produção, isso é fundamental para saber o que foi executado, quando, e se algo deu errado.

Exemplo no código:

private static final Logger LOGGER = LoggerFactory.getLogger(CategoriaService.class);

E dentro do método:

LOGGER.info("Entrou no método deletarCategoria com o id: {}", id);

Tipos de log que usamos:

  • info: para informações normais, como entrada no método
  • warn: para situações suspeitas, como um ID que não existe
  • error: para erros que precisam de atenção, como falhas de integridade

❌ O que acontece se algo der errado?

Imagine que a categoria a ser deletada:

  • Não existe (ID inválido)
  • Está sendo usada em outra tabela (como um produto vinculado a essa categoria)

Se você não tratar essas situações, sua API vai estourar um erro 500 (Internal Server Error) e o cliente vai receber uma mensagem genérica e confusa.


🛠️ Como capturamos esses erros com @ExceptionHandler

No Spring, usamos @ExceptionHandler para interceptar exceções específicas e retornar respostas personalizadas.

Exemplo no código:

@ExceptionHandler(DatabaseException.class)
public ResponseEntity<StandardError> databaseException(DatabaseException e, HttpServletRequest request){
StandardError error = new StandardError();
error.setTimestamp(Instant.now());
error.setStatus(HttpStatus.BAD_REQUEST.value());
error.setError("Database Exception");
error.setMessage(e.getMessage());
error.setPath(request.getRequestURI());

return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
}

O que isso faz:

  • Sempre que uma DatabaseException for lançada na aplicação…
  • O Spring vai capturar essa exceção automaticamente…
  • E vai montar uma resposta JSON amigável com status 400 e uma mensagem clara para o cliente.

Exemplo de resposta JSON:

{
"timestamp": "2025-05-04T18:27:00Z",
"status": 400,
"error": "Database Exception",
"message": "Não foi possível excluir a categoria. Ela pode estar vinculada a outros registros.",
"path": "/categoria/5"
}

✅ Resumo da Arquitetura

[Cliente DELETE /categoria/5] 
|
V
[CategoriaController]
|
V
[CategoriaService]
|
verifica se existe ID
|
+--> se não existe → lança ResourceNotFoundException
|
+--> tenta deletar
|
+--> se falha por integridade → lança DatabaseException
|
V
[ExceptionHandler] → responde com JSON amigável

📈 Resultado Final

Com esse padrão, sua API agora está:

  • Mais confiável
  • Mais clara para quem consome
  • E muito mais fácil de manter e debugar

👨‍💻 Código limpo = código vivo

Esse tipo de prática demonstra maturidade no desenvolvimento de APIs. Não basta só “fazer funcionar”, é preciso pensar na experiência de quem usa e na sanidade de quem mantém.

Gostou do post? Já implementava algo parecido?
Se tiver dúvidas, compartilha aqui nos comentários! 🧠💬

Categorized in:

Backend, Spring Boot, Uncategorized,