Migration complète vers PrimeFaces Freya - Corrections des incompatibilités et intégration de primefaces-freya-extension
This commit is contained in:
301
CORRECTIONS_TIMEOUT_VIEWEXPIRED.md
Normal file
301
CORRECTIONS_TIMEOUT_VIEWEXPIRED.md
Normal file
@@ -0,0 +1,301 @@
|
||||
# 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** :
|
||||
```properties
|
||||
# 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** :
|
||||
```properties
|
||||
# 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** :
|
||||
```properties
|
||||
# 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** :
|
||||
```bash
|
||||
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** :
|
||||
```properties
|
||||
# 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.java`
|
||||
- `CustomExceptionHandlerFactory.java`
|
||||
- Configuration dans `faces-config.xml`
|
||||
|
||||
**Stratégie intelligente** :
|
||||
```java
|
||||
// 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
|
||||
```bash
|
||||
# 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
|
||||
|
||||
```bash
|
||||
# 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
|
||||
|
||||
1. Accéder à : http://localhost:8082
|
||||
2. Se connecter avec Keycloak
|
||||
3. Naviguer vers : `/pages/user-manager/users/list.xhtml`
|
||||
4. **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 :
|
||||
|
||||
```java
|
||||
@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 :
|
||||
|
||||
```java
|
||||
// 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 :
|
||||
|
||||
```xhtml
|
||||
<!-- list.xhtml -->
|
||||
<p:dataTable value="#{userListBean.users}"
|
||||
lazy="true"
|
||||
paginator="true"
|
||||
rows="20">
|
||||
<!-- ... -->
|
||||
</p:dataTable>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Checklist de vérification
|
||||
|
||||
- [x] Keycloak accessible sur http://localhost:8180
|
||||
- [x] Realm `lions-user-manager` existe
|
||||
- [x] Authentification admin `admin/admin` sur realm `master` fonctionne
|
||||
- [x] Timeout REST Client augmenté à 90s (DEV)
|
||||
- [x] Keycloak Admin Client configuré sur realm `master`
|
||||
- [x] Timeout Keycloak Admin augmenté à 60s
|
||||
- [x] MyFaces : Nombre de vues augmenté (100)
|
||||
- [x] MyFaces : Timeout client augmenté (2h)
|
||||
- [x] Redirection ViewExpired configurée
|
||||
- [x] **Permissions HTTP configurées en DEV (corrige le 403 Forbidden)**
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Résultat attendu
|
||||
|
||||
Après redémarrage :
|
||||
1. ✅ Pas de timeout 30s
|
||||
2. ✅ Chargement réussi (peut prendre 10-60s selon le nombre d'utilisateurs)
|
||||
3. ✅ Pas de ViewExpiredException
|
||||
4. ✅ Liste des utilisateurs affichée
|
||||
|
||||
---
|
||||
|
||||
**Date** : 2025-12-25
|
||||
**Version** : 1.0.0
|
||||
**Statut** : ✅ CORRECTIONS APPLIQUÉES - Redémarrage requis
|
||||
Reference in New Issue
Block a user