0

I'm trying to intercept all exceptions that can happen in a REST API request, create a custom message to each one and to add them both to the response.

The request below has two errors, one in the field tipo and other in the field formato. The default behavior is to stop in the first exception and throw. And after this the deserialization of the request stops. But I want to intercept the two exceptions and accumulate them to show both custom messages in the response.

{
    "titulo": "1984",
    "autor": "Georgesss Orwell",
    "editora": "Penguin Classics Companhia das Letras",
    "tipo": "LIVsRO",
    "formato": "FISIsCO",
    "quantidadePaginas": "392",
    "edicao": 1,
    "anoEdicao": 2020,
    "generos": ["Literatura britânica", "Ficção", "Ficção britânica", "Distopia"],
    "acabamento": "BROCHURA",
    "idioma": "PORTUGUES",
    "pais": "BRASIL",
    "quantideLivros": 1
}

I'm using Java 17 with Spring Boot 2.7.5 in Windows 10.

Below is the approach that I've tried:

I've created a Global Exception Handler:

@ControllerAdvice
public class GlobalExceptionHandler {

    private List<Exception> exceptions = new ArrayList<>();

    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<Object> handleHttpMessageNotReadable(HttpMessageNotReadableException ex) {
        exceptions.add(ex);
        return ResponseEntity.badRequest().body("Erro na desserialização do JSON");
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<Object> handleException(Exception ex) {
        exceptions.add(ex);
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Erro interno do servidor");
    }

    @ExceptionHandler(AccumulatedExceptions.class)
    public ResponseEntity<Object> handleAccumulatedExceptions(AccumulatedExceptions ex) {
        List<String> exceptionMessages = new ArrayList<>();
        for (Exception exception : ex.getExceptions()) {
            exceptionMessages.add(exception.getMessage());
        }
        return ResponseEntity.badRequest().body(exceptionMessages);
    }

    @PostConstruct
    public void clearExceptions() {
        exceptions.clear();
    }

    public List<Exception> getExceptions() {
        return exceptions;
    }

}

With this custom exception:

public class AccumulatedExceptions extends RuntimeException {
    private List<Exception> exceptions = new ArrayList<>();

    public AccumulatedExceptions(List<Exception> exceptions) {
        this.exceptions = exceptions;
    }

    public List<Exception> getExceptions() {
        return exceptions;
    }
}

And this is my controller:

@RestController
@RequestMapping(path = "livros")
@CrossOrigin
public class LivroController {

    @Autowired
    private LivroService service;

    @Autowired
    private LivroRepository livroRepository;

    @Autowired
    private LivroResponse response;

    private GlobalExceptionHandler globalExceptionHandler;

    public LivroController(GlobalExceptionHandler globalExceptionHandler) {
        this.globalExceptionHandler = globalExceptionHandler;
    }

    @GetMapping(path = "getLivros")
    public List<Livro> getLivros() {
        return livroRepository.findAll();
    }

    @PostMapping(path = "addLivro")
    public ResponseEntity<String> addLivro(@RequestBody LivroRequest request) {

            List<Exception> exceptions = globalExceptionHandler.getExceptions();
            if (!exceptions.isEmpty()) {
               globalExceptionHandler.clearExceptions();
               throw new AccumulatedExceptions(exceptions);
           }

           return ResponseEntity.ok("Livro criado com sucesso");

    }

}

Is it possible to do what I want or did I go crazy?

Let me know if you need more information from my side.

Thanks in advance.

0 Answers0