This repository has been archived on 2026-01-03. You can view files and clone it, but cannot push or open issues or pull requests.
Files
lions-user-manager/REFACTORING_USER_SERVICE_ERROR_HANDLING.md

7.4 KiB

🔧 Refactoring UserServiceImpl - Gestion des Erreurs de Connexion

Date: 2025-12-18


📋 Problème Initial

NullPointerException dans createUser (ligne 196)

Symptôme : Lorsque le client REST ne peut pas se connecter au service Keycloak et retourne null, une NullPointerException se produit à la ligne 196 lors de l'appel à response.getStatus().

Cause : Aucune vérification de nullité pour l'objet Response retourné par usersResource.create(userRep).


Solution Implémentée

1. Création d'une Exception Personnalisée

Fichier créé : lions-user-manager-server-impl-quarkus/src/main/java/dev/lions/user/manager/service/exception/KeycloakServiceException.java

Classes d'exception :

  • KeycloakServiceException : Exception de base pour les erreurs Keycloak
  • KeycloakServiceException.ServiceUnavailableException : Pour les erreurs de connexion (503, 502)
  • KeycloakServiceException.TimeoutException : Pour les timeouts (504)

Avantages :

  • Messages d'erreur clairs et spécifiques
  • Codes HTTP préservés pour le debugging
  • Hiérarchie d'exceptions pour gestion fine

2. Méthode Utilitaire validateResponse

Fonction : Valide une réponse HTTP du service Keycloak.

Vérifications :

  • Réponse non null
  • Code de statut HTTP attendu
  • Gestion des codes d'erreur (400, 401, 403, 404, 409, 500, 502, 503, 504)

Utilisation :

Response response = usersResource.create(userRep);
validateResponse(response, "création de l'utilisateur", Response.Status.CREATED.getStatusCode());

3. Méthode Utilitaire handleConnectionException

Fonction : Gère les exceptions de connexion et les convertit en KeycloakServiceException appropriée.

Détection automatique :

  • ConnectException
  • SocketTimeoutException
  • Messages contenant "Connection", "timeout", "refused", "Unable to connect"

Utilisation :

catch (Exception e) {
    handleConnectionException(e, "création de l'utilisateur");
}

4. Refactoring de createUser

Avant :

var response = usersResource.create(userRep);
if (response.getStatus() != 201) {
    throw new RuntimeException("Échec de la création...");
}

Après :

Response response = usersResource.create(userRep);

// Vérifier si la réponse est null (erreur de connexion)
if (response == null) {
    throw new KeycloakServiceException.ServiceUnavailableException(
        "Impossible de se connecter au service Keycloak...");
}

// Vérifier le code de statut HTTP
int status = response.getStatus();
if (status != Response.Status.CREATED.getStatusCode()) {
    // Gérer les différents codes d'erreur HTTP
    if (status == 400) { ... }
    else if (status == 409) { ... }
    else if (status == 503 || status == 502) { ... }
    // ...
}

Améliorations :

  • Vérification de nullité avant getStatus()
  • Vérification de getLocation() avant utilisation
  • Gestion spécifique des codes HTTP d'erreur
  • Messages d'erreur clairs et actionnables

5. Refactoring des Autres Méthodes

Méthodes refactorisées :

  • createUser - Vérification Response null + codes HTTP
  • updateUser - Vérification UserResource et UserRepresentation null
  • deleteUser - Vérification UserResource et UserRepresentation null
  • activateUser - Vérification UserResource et UserRepresentation null
  • deactivateUser - Vérification UserResource et UserRepresentation null
  • sendVerificationEmail - Vérification UserResource null
  • logoutAllSessions - Vérification UserResource null + getUserSessions null
  • searchUsers - Utilisation de handleConnectionException
  • getUserByUsername - Vérification users null
  • getUserByEmail - Vérification users null
  • getUserById - Utilisation de handleConnectionException
  • setPassword - Utilisation de handleConnectionException

📊 Gestion des Codes HTTP

Codes Gérés

Code Exception Message
400 KeycloakServiceException "Données invalides"
401 KeycloakServiceException "Non autorisé"
403 KeycloakServiceException "Accès interdit"
404 KeycloakServiceException "Ressource non trouvée"
409 KeycloakServiceException "Conflit"
500 KeycloakServiceException "Erreur serveur interne Keycloak"
502 ServiceUnavailableException "Service Keycloak indisponible"
503 ServiceUnavailableException "Service Keycloak indisponible"
504 TimeoutException "Timeout lors de l'opération"
null ServiceUnavailableException "Impossible de se connecter au service Keycloak"

🔍 Détection des Erreurs de Connexion

Types d'Exceptions Détectées

  1. Exceptions Java Standard :

    • ConnectException
    • SocketTimeoutException
  2. Messages d'Erreur :

    • Contient "Connection"
    • Contient "timeout"
    • Contient "refused"
    • Contient "Unable to connect"

Exemple de Détection

catch (Exception e) {
    String errorMessage = e.getMessage();
    if (e instanceof ConnectException || 
        e instanceof SocketTimeoutException ||
        (errorMessage != null && errorMessage.contains("Connection"))) {
        throw new KeycloakServiceException.ServiceUnavailableException(...);
    }
}

🎯 Résultat

Avant

  • NullPointerException si Response est null
  • Messages d'erreur génériques (RuntimeException)
  • Pas de distinction entre types d'erreurs
  • Pas de gestion des codes HTTP spécifiques

Après

  • Vérification de nullité systématique
  • Exceptions spécifiques avec messages clairs
  • Distinction entre erreurs de connexion, validation, autorisation, etc.
  • Gestion complète des codes HTTP
  • Logs détaillés pour le debugging

📝 Exemple d'Utilisation

Cas 1 : Connexion Échouée (Response null)

Response response = usersResource.create(userRep);
if (response == null) {
    throw new KeycloakServiceException.ServiceUnavailableException(
        "Impossible de se connecter au service Keycloak pour créer l'utilisateur: " + user.getUsername());
}

Cas 2 : Code HTTP d'Erreur

int status = response.getStatus();
if (status == 409) {
    throw new IllegalArgumentException("L'utilisateur existe déjà (conflit détecté par Keycloak)");
} else if (status == 503) {
    throw new KeycloakServiceException.ServiceUnavailableException("Service Keycloak indisponible");
}

Cas 3 : Exception de Connexion

catch (Exception e) {
    handleConnectionException(e, "création de l'utilisateur " + user.getUsername());
}

🔄 Migration des Autres Méthodes

Toutes les méthodes qui utilisent le client REST Keycloak ont été refactorisées pour :

  1. Vérifier les objets null retournés
  2. Utiliser handleConnectionException pour les erreurs
  3. Lever des KeycloakServiceException au lieu de RuntimeException
  4. Gérer spécifiquement les codes HTTP d'erreur

📚 Références


Document créé le: 2025-12-18