Retour aux articles

Gestion des exceptions et erreurs : une approche robuste et centralisée avec Spring Boot et Angular

Gestion des exceptions et erreurs : une approche robuste et centralisée avec Spring Boot et Angular | Laty Gueye Samba - Développeur Full Stack Dakar Sénégal, Expert Java Spring Boot Angular
```html

Gestion des exceptions et erreurs : une approche robuste et centralisée avec Spring Boot et Angular

Une application moderne doit gérer les erreurs de façon prévisible, sécurisée et homogène. Cette approche réduit la complexité, améliore l’observabilité et garantit une expérience utilisateur cohérente. Avec Spring Boot côté serveur et Angular côté client, il est possible d’implémenter une stratégie de gestion des exceptions à la fois robuste et centralisée.

Objectifs d’une gestion centralisée

La centralisation vise principalement :

  • Uniformiser les formats de réponse d’erreur (code, message, détail, corrélation).
  • Sécuriser les informations sensibles (ne pas exposer de stacktrace au client).
  • Améliorer l’observabilité via des identifiants de corrélation et un logging structuré.
  • Faciliter le diagnostic et la maintenance.

Spring Boot : centraliser les exceptions avec @ControllerAdvice

Spring Boot permet d’intercepter les erreurs à un niveau global grâce à @ControllerAdvice et @ExceptionHandler. Cette couche transforme les exceptions en réponses HTTP cohérentes (souvent via Problem Details ou un contrat JSON maison).

Modèle de réponse d’erreur

Un contrat d’erreur standard aide le client à interpréter et afficher correctement les messages.

Gestion globale des exceptions

Le conseil ci-dessous illustre une approche structurée : mappage des exceptions métiers, validation, et erreurs génériques.

handleValidation( MethodArgumentNotValidException ex, HttpServletRequest request) { String correlationId = CorrelationIdUtil.fromRequest(request); ApiError error = new ApiError( "VALIDATION_ERROR", "Requête invalide : vérification des champs échouée.", request.getRequestURI(), correlationId ); return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error); } @ExceptionHandler(ResourceNotFoundException.class) public ResponseEntity handleNotFound( ResourceNotFoundException ex, HttpServletRequest request) { String correlationId = CorrelationIdUtil.fromRequest(request); ApiError error = new ApiError( "NOT_FOUND", ex.getMessage(), request.getRequestURI(), correlationId ); return ResponseEntity.status(HttpStatus.NOT_FOUND).body(error); } @ExceptionHandler(Exception.class) public ResponseEntity handleGeneric( Exception ex, HttpServletRequest request) { String correlationId = CorrelationIdUtil.fromRequest(request); // Log structuré côté serveur // logger.error("Unhandled exception. correlationId={}", correlationId, ex); ApiError error = new ApiError( "INTERNAL_SERVER_ERROR", "Une erreur inattendue est survenue. Référence : " + correlationId, request.getRequestURI(), correlationId ); return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error); } } ]]>

Corrélation et traçabilité

Pour relier les requêtes et les logs, un correlationId est généralement propagé via un en-tête HTTP (ex. X-Correlation-Id). Un filtre peut être utilisé pour l’initialiser.

Spring Boot : distinguer erreurs techniques et erreurs métier

Une erreur métier (ex. ressource inexistante, état invalide, droits insuffisants) doit être mappée sur un code applicatif et un HTTP status pertinent. À l’inverse, les erreurs techniques (null pointer, échec d’intégration, etc.) doivent rester génériques côté client tout en étant détaillées dans les logs.

Exemple de hiérarchie d’exceptions

Angular : une stratégie centralisée de gestion d’erreurs

Côté client, il est recommandé d’industrialiser le traitement des erreurs via un HttpInterceptor. Cela évite la duplication dans chaque composant et garantit un comportement homogène.

Modèle d’erreur côté Angular

HttpInterceptor pour mapper les réponses en actions UI

L’intercepteur peut gérer : redirections (401/403), notifications (400), et message générique (500).

, next: HttpHandler): Observable> { return next.handle(req).pipe( catchError((error: HttpErrorResponse) => { const apiError: any = error.error; // Exemples de décisions UI switch (error.status) { case 400: // notification toast : apiError.message break; case 401: // redirection vers login break; case 403: // notification "accès refusé" break; case 404: // notification "ressource introuvable" break; default: // message générique + correlationId si disponible break; } return throwError(() => error); }) ); } } ]]>

Enregistrement de l’intercepteur

Contrat API : cohérence des codes et messages

Une réponse d’erreur devrait être stable et suffisamment informative pour le client, sans révéler d’implémentation interne. Un schéma minimal utile inclut :

  • code : identifiant applicatif (ex. VALIDATION_ERROR, NOT_FOUND).
  • message : texte orienté utilisateur.
  • path : utile au diagnostic.
  • correlationId : référence pour les logs.

Exemple de réponse JSON

Bonnes pratiques de sécurité et d’ergonomie

  • Ne pas exposer les détails techniques au client (stacktrace, requêtes internes).
  • Log structuré côté serveur avec correlationId.
  • Messages stables : éviter les variations inutiles qui compliquent la traduction côté UI.
  • Statuts HTTP corrects : BAD_REQUEST pour validation, NOT_FOUND pour absence, FORBIDDEN/UNAUTHORIZED pour sécurité.

Résumé

En combinant @ControllerAdvice et un HttpInterceptor, une application Spring Boot + Angular obtient une gestion des erreurs centralisée, cohérente et traçable. La séparation entre erreurs métier et erreurs techniques permet de préserver la sécurité tout en améliorant l’expérience utilisateur et la capacité de diagnostic.

Checklist rapide

  • Spring Boot : mapping global via @ControllerAdvice.
  • Contrat d’erreur : code + message + path + correlationId.
  • Logs : enrichis avec correlationId, sans fuite de stacktrace au client.
  • Angular : traitement centralisé via HttpInterceptor.
  • UI : notifications et redirections basées sur le statut HTTP.

À propos de l'auteur

Laty Gueye Samba est développeur Full Stack basé à Dakar, Sénégal. Spécialiste des écosystèmes Java / Spring Boot et Angular.

Contact : latygueyesamba@gmail.com  |  Dakar, Sénégal