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 RESTLOGGER
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çõesPOST
→ criar algoPUT
→ atualizarDELETE
→ 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 aoDELETE /categoria/5
, por exemplo.@PathVariable Long id
: extrai oid
da URL.categoriaService.deletarCategoria(id)
: chama o método responsável por excluir a categoria.ResponseEntity.noContent()
: retorna o status HTTP204
(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étodowarn
: para situações suspeitas, como um ID que não existeerror
: 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! 🧠💬