
Personnalisation des réponses d'erreur
Apprenez à personnaliser les réponses d'erreur pour les API REST (ResponseEntity) et les applications web (pages d'erreur HTML) dans Spring Boot via @ExceptionHandler et ErrorController.
Au-delà des erreurs par défaut : Une expérience utilisateur soignée
La gestion globale des exceptions avec @ControllerAdvice et @ExceptionHandler (vue dans la section précédente) est un excellent point de départ. Cependant, les réponses générées par défaut (la page Whitelabel pour les navigateurs ou une structure JSON basique pour les API) ne sont souvent pas idéales pour une application en production.
Une page d'erreur Whitelabel manque de personnalité et d'informations utiles pour l'utilisateur final. De même, une réponse d'erreur JSON par défaut peut manquer de détails structurés ou ne pas correspondre au format attendu par les clients de l'API. La personnalisation des réponses d'erreur est donc essentielle pour offrir une expérience utilisateur cohérente et fournir des informations pertinentes aux développeurs ou aux utilisateurs finaux en cas de problème.
Spring Boot offre plusieurs niveaux de personnalisation, que ce soit pour retourner des structures d'erreur spécifiques pour les API REST ou pour afficher des pages d'erreur HTML personnalisées dans les applications web traditionnelles.
Personnalisation pour les API REST (`ResponseEntity`)
Lorsque vous gérez des exceptions dans le contexte d'une API REST (typiquement avec des contrôleurs annotés @RestController), l'objectif est de retourner une ResponseEntity qui contient non seulement un statut HTTP approprié (4xx pour les erreurs client, 5xx pour les erreurs serveur) mais aussi un corps de réponse structuré (généralement en JSON) décrivant l'erreur.
On utilise généralement @ExceptionHandler au sein d'une classe @ControllerAdvice pour intercepter des exceptions spécifiques et construire cette ResponseEntity personnalisée. Il est courant de définir une classe DTO (Data Transfer Object) simple pour représenter la structure de la réponse d'erreur.
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import java.time.LocalDateTime;
// DTO pour une réponse d'erreur structurée
class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String error;
private String message;
private String path;
// Constructeur, Getters & Setters...
public ErrorResponse(HttpStatus status, String message, String path) {
this.timestamp = LocalDateTime.now();
this.status = status.value();
this.error = status.getReasonPhrase();
this.message = message;
this.path = path;
}
// Getters...
}
// Exception personnalisée (exemple)
class ResourceNotFoundException extends RuntimeException {
public ResourceNotFoundException(String message) {
super(message);
}
}
@ControllerAdvice
public class ApiExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public ResponseEntity handleResourceNotFoundException(ResourceNotFoundException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
HttpStatus.NOT_FOUND,
ex.getMessage(),
request.getDescription(false).replace("uri=", "")
);
return new ResponseEntity<>(errorResponse, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(MethodArgumentNotValidException.class) // Pour les erreurs de validation @Valid
public ResponseEntity Cette approche permet de standardiser le format des réponses d'erreur de votre API, facilitant leur traitement par les clients.
Personnalisation pour les applications web (Pages HTML)
Pour les applications web traditionnelles qui rendent des vues HTML, la personnalisation vise à remplacer la page d'erreur Whitelabel par des pages plus informatives et intégrées au design de l'application.
Pages d'erreur statiques : La méthode la plus simple consiste à fournir des fichiers HTML statiques pour des codes d'erreur spécifiques. Spring Boot recherche automatiquement ces fichiers dans les emplacements suivants (par ordre de priorité) :
src/main/resources/static/error/src/main/resources/templates/error/
Les noms de fichiers doivent correspondre aux codes de statut HTTP ou utiliser des masques :
404.html: Pour les erreurs 404 Not Found.5xx.html: Pour toutes les erreurs serveur (500, 501, etc.) si un fichier spécifique (ex:500.html) n'est pas trouvé.error.html: Page d'erreur par défaut utilisée si aucun fichier spécifique ou masque ne correspond.
Pages d'erreur dynamiques (avec Thymeleaf, Freemarker, etc.) : Si vous souhaitez que vos pages d'erreur soient dynamiques (par exemple, pour afficher des détails de l'erreur ou utiliser des layouts communs), vous pouvez les placer dans le répertoire src/main/resources/templates/error/. Spring Boot tentera de résoudre une vue portant le nom du code d'erreur (ex: `error/404`) en utilisant le moteur de templates configuré.
Lorsque Spring Boot rend une vue d'erreur (statique ou dynamique), il ajoute plusieurs attributs au modèle que vous pouvez utiliser dans votre page :
${timestamp}: Date et heure de l'erreur.${status}: Code de statut HTTP (ex: 404, 500).${error}: Phrase de raison du statut HTTP (ex: Not Found, Internal Server Error).${message}: Message d'erreur détaillé (s'il est disponible et si `server.error.include-message` n'est pas `never`).${path}: Chemin URL qui a déclenché l'erreur.${exception}: Nom complet de la classe de l'exception (si `server.error.include-exception` est `true`).${trace}: La stack trace (si `server.error.include-stacktrace` est `always` ou `on-trace-param`). Attention : Ne pas exposer la stack trace en production !
Exemple de page d'erreur Thymeleaf (`src/main/resources/templates/error.html`) :
Oups! Une erreur est survenue
Erreur Code - Raison
Désolé, une erreur s'est produite.
Message: ...
Sur le chemin: /url
Retour à l'accueilUtiliser `@ExceptionHandler` pour les vues : Vous pouvez également utiliser des méthodes @ExceptionHandler dans un @ControllerAdvice pour retourner directement le nom d'une vue d'erreur personnalisée et y ajouter des attributs spécifiques au modèle.
@ControllerAdvice
public class WebExceptionHandler {
@ExceptionHandler(ResourceNotFoundException.class)
public String handleResourceNotFound(ResourceNotFoundException ex, Model model) {
model.addAttribute("errorMessage", ex.getMessage());
// Retourne le nom logique de la vue d'erreur personnalisée
// Ex: /templates/errors/resource-not-found.html
return "errors/resource-not-found";
}
}
Contrôle avancé avec `ErrorController`
Pour un contrôle total sur la manière dont les erreurs sont gérées, en particulier pour le mapping `/error` par défaut, vous pouvez implémenter votre propre org.springframework.boot.web.servlet.error.ErrorController. Spring Boot fournit une implémentation par défaut, BasicErrorController, qui gère le rendu des pages d'erreur HTML ou des réponses JSON en fonction de l'en-tête Accept de la requête.
Implémenter votre propre ErrorController vous permet de définir précisément le contenu retourné pour différentes erreurs ou différents types de contenu. Vous interagirez souvent avec l'interface ErrorAttributes (et son implémentation par défaut DefaultErrorAttributes) pour récupérer les détails de l'erreur et décider comment les présenter.
C'est une approche plus avancée, généralement réservée aux cas où les méthodes de personnalisation standard (pages statiques/dynamiques, @ExceptionHandler) ne suffisent pas.
Considérations finales
Lors de la personnalisation des erreurs :
- Soyez cohérent : Appliquez un style et une structure cohérents à toutes vos réponses/pages d'erreur.
- Pensez à l'utilisateur : Fournissez des messages clairs et, si possible, des suggestions sur la manière de résoudre le problème ou de contacter le support.
- Sécurité : Ne divulguez pas d'informations sensibles (stack traces complètes, détails de configuration) dans les réponses d'erreur en environnement de production. Utilisez les propriétés `server.error.include-*` pour contrôler ce qui est inclus.
- Journalisation (Logging) : Assurez-vous de toujours journaliser les détails complets des erreurs serveur côté serveur pour le débogage, même si vous ne montrez qu'un message générique à l'utilisateur.
- Internationalisation : Utilisez
MessageSourcepour fournir des messages d'erreur traduits, que ce soit dans les réponses API ou les pages HTML.
Une personnalisation réfléchie des réponses d'erreur améliore significativement la qualité perçue et la maintenabilité de votre application Spring Boot.