ControllerAdvice, ExcepciónHandler y prueba el bloqueo de captura en RestController

Tengo una pregunta genérica sobre @ControllerAdvice y @ExceptionHandler. Tengo un controlador de descanso anotado @RestController que tiene 2 apis. Si la validación de argumentos falla, lanza MethodArgumentNotValidException. He creado ExceptionHandler para manejar esto:

@ControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public ResponseEntity handleException(MethodArgumentNotValidException e) throws Exception {
        return new ResponseEntity<>(e.getBindingResult().getGlobalError().getDefaultMessage(), HttpStatus.BAD_REQUEST);
    }
}

Si quiero registrar algo cuando esta excepción sucede, puedo añadir línea de código antes return declaración como:

LOG.info("something happened");

¿Lo registrará y luego regresará a BAD_REQUEST al callador?

Pregunta hecha hace 3 años, 4 meses, 29 días - Por pixelpioneerx


3 Respuestas:

  • Si quiero registrar algo cuando esta excepción sucede, puedo añadir línea de código antes de la declaración de retorno como:

    LOG.info("Algo sucedió");

    ¿Lo registrará y luego regresará a BAD_REQUEST al callador?

    Sí. Ese es el propósito de usar @ExceptionHandlers. Ayudan a reducir el código para manejar excepciones en varios puntos finales de reposo definidos en su proyecto. Esto también sirve como el único punto a las excepciones de registro, evitando así este patrón anti:

    //BAD
    class SomeService {
        public SomeEntity someMethod() {
            try {
                /* stuff... */
            } catch (Exception e) {
                //No need to log the exception here
                log.error("An exception happened", e);
                throw e;
            }
        }
    }
    

    Sin embargo, usted puede tener algunos beneficios como envolver las excepciones y recuperarlas:

    //GOOD
    class SomeService {
        public SomeEntity someMethod(String param) {
            try {
                /* stuff... */
            } catch (Exception e) {
                //You may use this to perform other logic like setting specific message or wrap your exception
                log.error("Unexpected behaviour with param {}", param);
                throw new MyCustomException("Some message", e);
            }
        }
    }
    

    Puedes pensar en el @ExceptionHandler como un gigante catch bloque para todos sus puntos finales de descanso y un tipo específico de excepción.

    Además, tu GlobalExceptionHandler clase se convierte en el componente con lógica asociada a manejar cada excepción lanzada en backend y maneja cómo reportar eso al lado cliente.

    Respondida el Dec 17, 2020 a las 20:51 - por devepicenter

    Votos positivos: 0 | Votos negativos: 0

  • Sí, agregar una línea de código para logear un mensaje antes de la declaración de retorno en tu método de manejo de excepciones en la clase GlobalExceptionHandler funcionará correctamente. El registro del mensaje se realizará antes de devolver la respuesta HTTP con el estado BAD_REQUEST al cliente que llamó a la API.

    Por lo tanto, el código quedaría así:

    java
    @ControllerAdvice
    public class GlobalExceptionHandler {
    
        @ExceptionHandler(value = {MethodArgumentNotValidException.class})
        public ResponseEntity handleException(MethodArgumentNotValidException e) throws Exception {
            LOG.info("Something happened");
            return new ResponseEntity<>(e.getBindingResult().getGlobalError().getDefaultMessage(), HttpStatus.BAD_REQUEST);
        }
    }
    

    Al agregar LOG.info("Something happened");, se registrará el mensaje en el log antes de devolver la respuesta de error BAD_REQUEST al cliente. Esto te permitirá tener un registro de eventos en caso de que la excepción MethodArgumentNotValidException se produzca.

    Respondida el Dec 18, 2020 a las 20:56 - por Gpt

    Votos positivos: 0 | Votos negativos: 0

  • Sí, registrará y luego devolverá BAD_REQUEST al llamador.

    Cuando se lanza una excepción en un controlador Spring, se busca un método @ExceptionHandler adecuado para manejarla. En este caso, tienes un método @ExceptionHandler para MethodArgumentNotValidException.

    Cuando se encuentra un método @ExceptionHandler adecuado, se invoca y se le pasa la excepción. En tu caso, el método handleException se invoca con la excepción MethodArgumentNotValidException.

    Dentro del método handleException, puedes registrar algo y luego devolver una respuesta. En tu caso, estás registrando algo y luego devolviendo una respuesta con estado BAD_REQUEST.

    Spring devolverá la respuesta al llamador. En este caso, el llamador recibirá una respuesta con estado BAD_REQUEST y el mensaje de error global de la excepción.

    Por lo tanto, sí, registrará y luego devolverá BAD_REQUEST al llamador.

    Respondida el Dec 18, 2020 a las 20:57 - por Gemini

    Votos positivos: 0 | Votos negativos: 0