1
resposta

[Dúvida] Pensando em Diversos e Possiveis Erros

Analisando e tentando me aprofundar um pouco, pesquisei algumas coisas e gostaria de uma ajuda: criei uma classe GlobalExceptionHandler que exnteds ResponseEntityExceptionHandler

algumas duvidas: 1º- Isso seria uma classe de erros customizados de acordo com o tipo da api? 2º- Quando devo ou não extender outra classe de 'Exception'? 3º- A classe extendida da ResponseEntityExceptionHandler, corresponde somente as entidades(DAO, Models, enfins...) que irão utilizar? 4º- Como saber ao longo do tempo quais metodos a mais criar? 5º - [Ajuda] Estou com um problema de return para erros de ConstraintViolationException no método criado, ele está retornando 400. 6º- Seria correto utilizar esta forma para excpetions em geral? Sem percisar tratar nada no controller?

@Slf4j(topic = "GLOBAL_EXCEPTION_HANDLER")
@RestControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {

    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    protected ResponseEntity<Object> handlerMethodArgumentNotValid(
            MethodArgumentNotValidException ex,
            HttpHeaders headers,
            HttpStatus status,
            WebRequest request) {

        EntityErrorResponse errorResponse = new EntityErrorResponse(
                HttpStatus.UNPROCESSABLE_ENTITY.value(),
                ex.getMessage());

        for (FieldError fieldError : ex.getBindingResult().getFieldErrors()) {
            errorResponse.addValidationError(fieldError.getField(), fieldError.getDefaultMessage());
        }
        return ResponseEntity.unprocessableEntity().body(errorResponse);
    }

    @ExceptionHandler(Exception.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    // Error 400 Bad Request
    public ResponseEntity<Object> handleAllUncaughtException(
            Exception ex,
            WebRequest request) {

        final String errorMessage = "Error não encontrado";
        // Log de erro
        log.error(errorMessage, ex);

        return buildErrorResponse(
                ex,
                errorMessage,
                HttpStatus.INTERNAL_SERVER_ERROR,
                request);
    }

    private ResponseEntity<Object> buildErrorResponse(
            Exception ex,
            String errorMessage,
            HttpStatus internalServerError,
            WebRequest request) {

        EntityErrorResponse errorResponse = new EntityErrorResponse(internalServerError.value(), errorMessage);

        return ResponseEntity.status(internalServerError).body(errorResponse);
    }

    @ExceptionHandler(DataIntegrityViolationException.class)
    @ResponseStatus(HttpStatus.CONFLICT)
    // Error 409 Conflict
    public ResponseEntity<Object> handleDataIntegrityViolationException(
            DataIntegrityViolationException ex,
            WebRequest request) {

        String errorMessage = ex.getMostSpecificCause().getMessage();

        log.error("Erro ao salvar novo médico com problema(s): " + errorMessage, ex);

        return buildErrorResponse(
                ex,
                errorMessage,
                HttpStatus.CONFLICT,
                request);
    }

    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
    // Error 422 Unprocessable Entity
    public ResponseEntity<Object> handleConstraintViolationException(
            ConstraintViolationException ex,
            WebRequest request) {

        log.error("Erro de validação do elemento " + ex);

        return buildErrorResponse(
                ex,
                HttpStatus.UNPROCESSABLE_ENTITY,
                request);
    }

    private ResponseEntity<Object> buildErrorResponse(
            Exception ex,
            HttpStatus httpStatus,
            WebRequest request) {
        return buildErrorResponse(ex, ex.getMessage(),httpStatus, request);
    }
}
1 resposta

Oi Neander!

Vamos por partes para responder suas dúvidas sobre a implementação do GlobalExceptionHandler:

  1. Classe de erros customizados: Sim, ao criar uma classe que estende ResponseEntityExceptionHandler, você está criando uma classe para tratar erros de forma customizada na sua API. Isso permite que você defina como diferentes tipos de exceções devem ser tratadas e quais respostas devem ser enviadas ao cliente.

  2. Extender outra classe de 'Exception': Você deve estender outra classe de 'Exception' quando quiser criar uma exceção customizada que represente um erro específico na sua aplicação. Por exemplo, se você tiver uma regra de negócio específica que não é coberta pelas exceções padrão do Java ou do Spring, você pode criar sua própria exceção estendendo RuntimeException ou Exception.

  3. ResponseEntityExceptionHandler e entidades: A classe ResponseEntityExceptionHandler não está limitada a entidades (DAO, Models, etc.). Ela é uma classe de conveniência do Spring que fornece métodos para tratar exceções comuns lançadas durante a manipulação de requisições HTTP. Você pode usá-la para tratar exceções de validação, erros de método não permitido, entre outros.

  4. Criar métodos ao longo do tempo: Para saber quais métodos criar ao longo do tempo, você deve monitorar os tipos de exceções que sua aplicação lança e quais delas precisam de um tratamento específico. Por exemplo, se você perceber que uma nova exceção está sendo lançada frequentemente e precisa de um tratamento especial, você pode adicionar um novo método no GlobalExceptionHandler para lidar com essa exceção.

  5. Erro de ConstraintViolationException retornando 400: O erro 400 (Bad Request) é apropriado para erros de validação de dados, mas se você deseja retornar um código diferente, como 422 (Unprocessable Entity), você pode ajustar o status na anotação @ResponseStatus ou no retorno do método. No seu caso, você já está retornando 422 para ConstraintViolationException, então parece que está correto. Se ainda estiver retornando 400, verifique se há outra configuração ou método que está interferindo.

  6. Utilizar esta forma para exceptions em geral: Sim, é uma boa prática centralizar o tratamento de exceções em um @RestControllerAdvice, como você fez. Isso mantém seu código de controle mais limpo e separado das preocupações de tratamento de erros. No entanto, para exceções específicas que precisam de um tratamento muito particular, você pode optar por tratá-las diretamente no controller.

Espero ter ajudado e bons estudos!