3
votes

Lier la gestion des exceptions à la classe @ControllerAdvice uniquement

J'ai une classe de contrôleur avec des méthodes REST qui peuvent lever diverses exceptions. J'ai décidé de gérer ces exceptions dans une classe distincte en utilisant @ControllerAdvice et @ExceptionHandler pour mes méthodes de gestionnaire. Cependant, j'ai le problème, que mes méthodes REST utilisent une annotation d'une autre bibliothèque. Cette bibliothèque intercepte une exception que ma méthode REST lève également. Maintenant que je gère les exceptions globalement et non via try / catch dans la méthode REST directement, mon exception est toujours interceptée par l'autre bibliothèque et non par ma propre méthode de gestionnaire. Apparemment, cette autre méthode de la bibliothèque que j'utilise gagne en raison de l'annotation. Comment puis-je lier la gestion des exceptions à ma propre classe pour éviter qu'elle ne soit interceptée par quelqu'un d'autre?

Ma méthode REST:

@ControllerAdvice
public class MyExceptionHandler {

 @ExceptionHandler(UnsupportedOperationException.class)
 public ResponseEntity<?> handleUnsupportedOperationException(UnsupportedOperationException e) {        
    return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
 }
}

Ma classe de gestionnaire d'exceptions: p>

@SomeLibraryAnnotation
@PostMapping(path = "/add", consumes = MediaType.APPLICATION_JSON_VALUE)
public HttpEntity< ? > addItem(@RequestHeader HttpHeaders headers, @RequestBody MyDTO myDTO)
  throws UnsupportedOperationException {
  doSomethingWith(myDTO);
  return ResponseEntity.status(HttpStatus.CREATED).build();
}

Comme la méthode de la bibliothèque intercepte également l'exception UnsupportedOperationException, elle gagne grâce à @SomeLibraryAnnotation et l'exception n'est jamais gérée dans ma classe de gestionnaire.


0 commentaires

3 Réponses :


0
votes

Vous pouvez essayer d'utiliser @Order ou @Priority dans la classe MyExceptionHandler , comme indiqué dans Setting Precedence of Multiple @ControllerAdvice @ExceptionHandlers .

Cela donnerait à Spring une opportunité d'utiliser votre classe au lieu de celle spécifiée par @SomeLibraryAnnotation . Cependant, sans savoir comment Spring interprète cette autre annotation lors de l'initialisation du contexte, ce n'est qu'une supposition.


1 commentaires

Merci pour la réponse. J'ai déjà essayé les deux annotations. Mais ça n'a pas marché. Je pense qu'ils ne fonctionnent que si j'ai plusieurs classes avec des annotations ControllerAdvice pour les prioriser. Mais ils n'ont aucun effet si j'utilise une annotation personnalisée d'une bibliothèque qui intercepte les mêmes exceptions.



0
votes

Avez-vous essayé d'écrire @ExceptionHandler dans votre contrôleur? Comme:

@RestController
@RequestMapping("/path")
public class TheController {

     @ExceptionHandler(UnsupportedOperationException.class)
     public ResponseEntity<?> handleUnsupportedOperationException(UnsupportedOperationException e) {        
        return ResponseEntity.status(HttpStatus.FORBIDDEN).body(e.getMessage());
     }
}

Peut-être que ce serait un ramassage et une exception avec une priorité plus élevée. Il est difficile de répondre sans savoir ce qu'est @SomeLibraryAnnotation ...


0 commentaires

0
votes

Ce ne sont que des règles du langage Java, c'est-à-dire que l'exception n'est plus non gérée , car elle a été gérée (prise dans un bloc catch) par votre autre bibliothèque. Ce que vous pouvez faire est de relancer (peut-être conditionnellement) une autre exception dans votre bibliothèque qui a intercepté l'exception d'origine et voir si @ExceptionHandler la gérera. Ce n'est peut-être pas parce que @ExceptionHandler gère les exceptions levées dans les classes Controller.

La deuxième approche serait de lever une exception qui n'est gérée que dans @ExceptionHandler, puis de la relancer pour qu'elle soit gérée dans une autre bibliothèque.

En d'autres termes, vous devez choisir où traiter la première exception lancée à l'origine.

La troisième approche consisterait à utiliser l'intercepteur AOP @AfterThrowing ou @Around , puis à exécuter la logique de votre choix.

Essence: il n'y a aucun moyen de gérer une exception à deux endroits à la fois. Cela a-t-il un sens?


0 commentaires