Bonjour,
J'ai une page de login. Si l'utilisateur est inconnu, on lui propose de créer un compte temporaire qu'il doit juste confirmer. S'il le fait, il accède alors aux fonctions principales de l'application.
Page de Login (je la stigmatise en la simplifiant, elle est dans une <table> en fait):
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7 <h:form> ${lbl.col_id}: <h:inputText id="id" value="#{login.id}" maxlength="8"/> ${lbl.col_nom}: <h:inputText id="nom" value="#{login.nom}" maxlength="50" /> ${lbl.col_prenom}: <h:inputText id="prénom" value="#{login.prénom}" maxlength="50" /> <h:commandButton action="#{login.login}" value="Entrer" /> </h:form>
Elle repose sur un @ManagedBean: LoginBean
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 @ManagedBean(name="login") @RequestScoped public class LoginBean extends BaseManagedBean { public String getId() {...} public String getNom() {...} public String getPrénom() {...} public void setId(String id) {...} public void setNom(String nom) {...} public void setPrénom(String prénom) {...} /** Action lorsque l'internaute veut s'authentifier. */ public String login() {...} /** Action lorsque l'internaute confirme la création d'un compte. */ public String confirmation() {...} }
La page de confirmation, qui est la direction que renvoie login() si l'utilisateur n'existe pas est celle-ci:
Page de confirmation:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 <h:form> ${lbl.col_id}: <h:inputText id="id" value="#{login.id}" readonly="yes" /> ${lbl.col_nom}: <h:inputText id="nom" value="#{login.nom}" readonly="yes" /> ${lbl.col_prenom}: <h:inputText id="prénom" value="#{login.prénom}" readonly="yes" /> <h:commandButton action="#{login.confirmation}" value="Confirmer" /> <h:commandButton action="#{login.annulation}" value="Annulation" /> </h:form>
Voici le symptôme:
1) L'internaute se logue sur la page de Login en entrant les valeurs d'un compte qui n'existe pas encore.
Dans les logs, je dump mon LoginBean:
Login de {id: A000000, nom: Test, prénom: Test, pointeur: web.authentification.login.LoginBean@2642ed}
2) La fonction login() fait la validation, remarque que le compte n'existe pas et choisit la destination "Page de confirmation".
3) La page de confirmation affiche à l'utilisateur les valeurs qu'il a entrées. L'utilisateur confirme.
==> L'utilisateur a bien vu les bonnes valeurs à l'écran sur cette nouvelle page.
==> Mais les logs, le dump de mon LoginBean dans la fonction confirmation() disent:
Confirmation de {id: null, nom: null, prénom: null, pointeur: web.authentification.login.LoginBean@305cca}
Epilogue: Un peu plus tard, le site web échouera parce qu'il ne transporte plus de valeurs utiles.
Bien sûr, si je mets mon @ManagedBean en @SessionScoped, je me sors de cette nasse. Mais cela me pose un problème de fond. Un problème de compréhension. Ce qui se passe ne me semble pas sain.
Voici mon interprétation:
Page 1: A l'affichage initial de la page de login, Le LoginBean @2642ed est créé en portée Requête, et l'internaute entre des valeurs dedans.
En validant cette page ce LoginBean @2642ed voit ses valeurs contrôlées: il est convenablement alimenté mais désigne un compte qui n'existe pas. On rejoint alors la page 2, de confirmation.
Page 2: A l'affichage initial de cette page de confirmation on est dans la phase Render Response ou Restore view, et l'on utilise le LoginBean @2642ed pour l'affichage. De là, on présente les bonnes valeurs.
Mais lorsque l'on confirme, on entre dans une nouvelle phase de requête - réponse.
Et à cette fin, JSF crée une nouvelle instance de LoginBean: @305cca. Vide. De là viennent tous mes problèmes.
Voici mon incompréhension où je souhaite votre éclairage.
Dans la page de confirmation,
Les champs ont les mêmes id que dans la page de login (ils se résolvent en HTML avec les mêmes identifiants JSF "j_idt14:id", par exemple).
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 <h:form> ${lbl.col_id}: <h:inputText id="id" value="#{login.id}" readonly="yes" /> ${lbl.col_nom}: <h:inputText id="nom" value="#{login.nom}" readonly="yes" /> ${lbl.col_prenom}: <h:inputText id="prénom" value="#{login.prénom}" readonly="yes" /> <h:commandButton action="#{login.confirmation}" value="Confirmer" /> <h:commandButton action="#{login.annulation}" value="Annulation" /> </h:form>
JSF a t-il forwardé ou pas ma requête entre la page de login et ma page de confirmation? C'est à dire: le bon affichage initial de la page de confirmation est-il du à un forward du bean @2642ed en requête qui a effectivement eu lieu, ou bien a t-il une autre cause?
Pourquoi JSF fait-il le choix de créer un nouveau LoginBean @305cca au moment où cette page est validée, alors qu'il pourrait poursuivre avec la requête précédente en la forwardant?
Mes possibilités?
- Est-ce moi qui ai oublié de mentionner quelque-chose qui aurait assuré qu'un forward se passe?
- Dois-je appeler une méthode de copie quelconque qui dirait à JSF: "Hé! copie vite le contenu de @2642ed dans @305cca avant de débuter la validation de la page de confirmation."?
- Ou dois-je annoter mon LoginBean en @SessionScoped, ce que j'ai fait, mais me met un peu mal à l'aise?
En vous remerciant de vos éclairages,
Grunt.
Partager