8.5 KiB
Corrections - Timeout & ViewExpiredException
🐛 Problèmes identifiés
1. Timeout 30s sur /api/users/search
Erreur lors du chargement des utilisateurs:
The timeout period of 30000ms has been exceeded while executing POST /api/users/search
Cause : Le backend met trop de temps à récupérer les utilisateurs depuis Keycloak Admin API.
Raisons possibles :
- Keycloak local lent au démarrage
- Beaucoup d'utilisateurs à récupérer
- Configuration Admin Client incorrecte (mauvais realm)
2. ViewExpiredException JSF
jakarta.faces.application.ViewExpiredException:
View "/pages/user-manager/users/list.xhtml" could not be restored.
Cause : La vue JSF a expiré pendant l'attente de la réponse du backend.
Raisons :
- Timeout trop long (30s) → Session JSF expire avant la fin
- Nombre limité de vues en session (50)
- Rechargement de page pendant le chargement
✅ Solutions appliquées
1️⃣ Augmentation du timeout REST Client
Fichier : lions-user-manager-client-quarkus-primefaces-freya/src/main/resources/application-dev.properties
Modification :
# Timeout augmenté pour éviter les erreurs lors des appels Keycloak lents
quarkus.rest-client."lions-user-manager-api".read-timeout=90000
Avant : 30 secondes (30000ms) - défini dans application.properties Après : 90 secondes (90000ms) en DEV
2️⃣ Correction du realm Admin Client
Fichier : lions-user-manager-server-impl-quarkus/src/main/resources/application-dev.properties
Problème : Le backend essayait de s'authentifier sur le realm lions-user-manager au lieu de master.
Modification :
# IMPORTANT: L'utilisateur admin se trouve dans le realm "master", pas "lions-user-manager"
lions.keycloak.server-url=http://localhost:8180
lions.keycloak.admin-realm=master # ← Changé de "lions-user-manager" à "master"
lions.keycloak.admin-client-id=admin-cli
lions.keycloak.admin-username=admin
lions.keycloak.admin-password=admin
# Timeout augmenté pour Keycloak local (peut être lent au démarrage)
lions.keycloak.timeout-seconds=60 # ← Ajouté
2️⃣.1 Ajout des permissions HTTP en DEV
Fichier : lions-user-manager-server-impl-quarkus/src/main/resources/application-dev.properties
Problème : Le backend retournait 403 Forbidden même avec la sécurité désactivée, car aucune permission HTTP explicite n'était définie.
Modification :
# Permissions HTTP - Accès public à tous les endpoints en DEV
quarkus.http.auth.permission.public.paths=/api/*,/q/*,/health/*,/metrics,/swagger-ui/*,/openapi
quarkus.http.auth.permission.public.policy=permit
Avant : Backend retournait 403 sur /api/users/search
Après : Tous les endpoints /api/* sont accessibles sans authentification en DEV
Vérification :
curl -X POST http://localhost:8180/realms/master/protocol/openid-connect/token \
-d "client_id=admin-cli" \
-d "grant_type=password" \
-d "username=admin" \
-d "password=admin"
# ✅ Retourne un access_token → Authentification réussie
3️⃣ Amélioration de la configuration MyFaces
Fichier : lions-user-manager-client-quarkus-primefaces-freya/src/main/resources/application.properties
Modifications :
# Nombre de vues en session augmenté
quarkus.myfaces.number-of-views-in-session=100 # Avant: 50
quarkus.myfaces.number-of-sequential-views-in-session=20 # Avant: 10
# Timeout client augmenté (2h au lieu de 1h)
quarkus.myfaces.client-view-state-timeout=7200000 # Avant: 3600000
# Mapping automatique activé
quarkus.myfaces.automatic-extensionless-mapping=true # Ajouté
Bénéfices :
- ✅ Plus de vues conservées en mémoire (50 → 100)
- ✅ Timeout client doublé (1h → 2h)
3️⃣.1 Handler personnalisé ViewExpiredException (NOUVEAU)
Fichiers créés :
CustomViewExpiredExceptionHandler.javaCustomExceptionHandlerFactory.java- Configuration dans
faces-config.xml
Stratégie intelligente :
// Si ViewExpiredException détectée:
if (session HTTP/OIDC valide) {
// La vue JSF a expiré, mais l'utilisateur est toujours authentifié
→ Rediriger vers la page d'origine (ou liste par défaut)
} else {
// La session HTTP/OIDC a expiré
→ Invalider la session
→ Rediriger vers /logout (Keycloak gère le logout complet)
}
Bénéfices :
- ✅ Déconnexion automatique si la session expire
- ✅ Pas de boucle de redirection vers pages protégées
- ✅ UX améliorée : seulement rafraîchir si session valide
- ✅ Sécurité : force la ré-authentification si nécessaire
🚀 Test de la configuration
Vérifier Keycloak
# Keycloak est accessible
curl -I http://localhost:8180
# → HTTP/1.1 302 Found ✅
# Le realm existe
curl http://localhost:8180/realms/lions-user-manager
# → {"realm":"lions-user-manager",...} ✅
# L'authentification admin fonctionne
curl -X POST http://localhost:8180/realms/master/protocol/openid-connect/token \
-d "client_id=admin-cli" -d "grant_type=password" \
-d "username=admin" -d "password=admin"
# → {"access_token":"..."} ✅
Redémarrer les applications
# Terminal 1 : Backend (redémarrage nécessaire pour application-dev.properties)
cd lions-user-manager/lions-user-manager-server-impl-quarkus
# Arrêter avec Ctrl+C puis:
mvn quarkus:dev
# Terminal 2 : Client (redémarrage nécessaire pour les nouvelles configs)
cd lions-user-manager/lions-user-manager-client-quarkus-primefaces-freya
# Arrêter avec Ctrl+C puis:
mvn quarkus:dev
Tester l'interface
- Accéder à : http://localhost:8082
- Se connecter avec Keycloak
- Naviguer vers :
/pages/user-manager/users/list.xhtml - Vérifier : La liste des utilisateurs se charge (peut prendre jusqu'à 90s)
📊 Résumé des timeouts
| Composant | Configuration | Avant | Après |
|---|---|---|---|
| REST Client (read) | quarkus.rest-client.*.read-timeout |
30s | 90s |
| Keycloak Admin | lions.keycloak.timeout-seconds |
30s | 60s |
| MyFaces Client State | quarkus.myfaces.client-view-state-timeout |
1h | 2h |
| Session HTTP | quarkus.http.session-timeout |
60min | 60min |
🔧 Si le problème persiste
Option 1 : Ajouter un cache côté backend
Éviter de requêter Keycloak à chaque fois :
@ApplicationScoped
public class UserCacheService {
private final Cache<String, List<UserDTO>> cache;
@Inject
UserService userService;
public UserCacheService() {
cache = Caffeine.newBuilder()
.expireAfterWrite(5, TimeUnit.MINUTES)
.maximumSize(100)
.build();
}
public List<UserDTO> getCachedUsers(String realm) {
return cache.get(realm, k -> userService.getAllUsers(realm, 0, 100).getUsers());
}
}
Option 2 : Pagination côté frontend
Limiter le nombre d'utilisateurs chargés :
// UserListBean.java
private static final int DEFAULT_PAGE_SIZE = 20; // Au lieu de 100+
public void loadUsers() {
UserSearchCriteriaDTO criteria = UserSearchCriteriaDTO.builder()
.realmName(realmName)
.page(currentPage)
.pageSize(DEFAULT_PAGE_SIZE) // ← Pagination stricte
.build();
UserSearchResultDTO result = userServiceClient.searchUsers(criteria);
// ...
}
Option 3 : Lazy loading
Charger les utilisateurs seulement quand nécessaire :
<!-- list.xhtml -->
<p:dataTable value="#{userListBean.users}"
lazy="true"
paginator="true"
rows="20">
<!-- ... -->
</p:dataTable>
✅ Checklist de vérification
- Keycloak accessible sur http://localhost:8180
- Realm
lions-user-managerexiste - Authentification admin
admin/adminsur realmmasterfonctionne - Timeout REST Client augmenté à 90s (DEV)
- Keycloak Admin Client configuré sur realm
master - Timeout Keycloak Admin augmenté à 60s
- MyFaces : Nombre de vues augmenté (100)
- MyFaces : Timeout client augmenté (2h)
- Redirection ViewExpired configurée
- Permissions HTTP configurées en DEV (corrige le 403 Forbidden)
🎯 Résultat attendu
Après redémarrage :
- ✅ Pas de timeout 30s
- ✅ Chargement réussi (peut prendre 10-60s selon le nombre d'utilisateurs)
- ✅ Pas de ViewExpiredException
- ✅ Liste des utilisateurs affichée
Date : 2025-12-25 Version : 1.0.0 Statut : ✅ CORRECTIONS APPLIQUÉES - Redémarrage requis