novembre
2007
Bonjour.
Dans ce billet, je vais présenter et expliquer les étapes de création du jeu GuessGame avec JSF et RichFaces.
Je vous rappèle donc le principe du jeu: Au départ, l’application génère un nombre aléatoire entre 1 et 100. L’utilisateur essaie de deviner ce nombre à travers un textbox. à chaque essais, l’application vous informe si c’est trop grand, trop petit ou si c’est la bonne réponse.
Sans plus tarder, attaquons la chose.
N.B: Je vais passer l’étape de configuration de RichFaces (voir post précédent).
On commence par le backing bean de notre jeu qui va génerer le nombre aléatoire et ensuite vérifier les essais du joueur.:
public class GameBean {
private int magic;
private Random random;
private String guess;
private String message;
public GameBean() {
random = new Random();
reset();
}
private void reset() {
magic = random.nextInt(100) + 1;
guess = "";
message = "...";
}
public String check() {
int x = 0;
try {
x = Integer.parseInt(guess);
if (x < 1 || x > 100)
throw new Exception();
} catch (Exception e) {
message = "Entrée non valide";
return null;
}
if (x < magic) {
message = "Trop petit !";
} else if (x > magic) {
message = "Trop grand !";
} else {
message = "Excellent ! Le nombre magique était " + magic;
}
return null;
}
public int getMagic() {
return magic;
}
public String getGuess() {
return guess;
}
public void setGuess(String guess) {
this.guess = guess;
}
public String getMessage() {
return message;
}
}
Voici rapidement de quoi il s’agit:
- Le champ magic (int) va contenir le nombre à deviner.
- Le champ random (java.util.Random) servira à générer les nombres aléatoires.
- Le champ guess (String) servira à receuillir les essais de l’utilisateur. Normalement, il devrait être de type int combiné avec un converter dans la page JSF, mais bon, j’ai omis ça pour simplifier la chose.
- Le champ message servira à contenir la réponse de l’application suite à un essai du joueur (trop grand, trop petit, etc.)
- La méthode privée reset() sera appelée à l’initialisation du jeu pour générer le nombre aléatoire.
- La méthode check() est une action JSF (type de retour String, sans paramètres) quis era appelé à chaque entrée utilisateur pour la vérifier.
N.B: check retourne toujours null, et ce pour rester dans la même page. - Les méthodes restantes ne sont que des getters et des setters pour exposer nos champs à l’EL (aux pages JSF).
Passons maintenant à la partie présentation. Notre jeu tiendra dans une seule page.
Normalement (sans Ajax), nous aurions déclaré dans
<h:form>
<h:inputText value="#{gameBean.guess}" />
<h:outputText value="#{gameBean.message}" />
<h:commandButton value="Check" action="#{gameBean.check}" />
</h:form>
En cliquant sur le commandButton « check », le formulaire sera envoyé et traité par JSF, ce qui implique entre autre que gameBean.guess se verra affecter la valeur entrée dans le champ texte. Ensuite, la méthode gameBean.check() à sera appelé qui va mettre dans le champ message le résultat de la vérification et retournera null. JSF retournera la main alors à la même page qui sera rendu à nouveau mais avec le message adéquat.
Nous allons maintenant ajaxifier la chose avec RichFaces (ou plus exactement avec Ajax4Jsf).
Dans une première passe (et là, c’est vraiment magique ;-)), on se contente de remplacer le composant form de JSF par celui d’Ajax4Jsf, comme ça:
<a4j:form>
<h:inputText value="#{gameBean.guess}" />
<h:outputText value="#{gameBean.message}" />
<h:commandButton value="Check" action="#{gameBean.check}" />
</a4j:form>
N.B: l’uri qu’il faut importer pour utiliser les comosants a4j est: http://richfaces.org/a4j
Relançons l’application.
A première vue rien ne se passe: suite à un clic sur le commandButton, absolument rien ne se passe … mais en fait si ! Pour s’en convaincre, il suffit d’ajouter un simple :
System.out.println(« check « +guess);
au tout début de GameBean.check().
Réessayez de nouveau … et vous remarquerez que chaque fois que l’on appuie sur le commandButton, une ligne telle que celle-ci s’ajoute dans la console (d’eclipse par exemple):
check 45 check 23
Explication ?
Mais alors, pourquoi le message ne change pas ?
C’est simple, il suffit d’indiquer à
Notre code devient donc:
<a4j:form reRender="out" >
<h:inputText value="#{gameBean.guess}" />
<h:outputText value="#{gameBean.message}" id="out" />
<h:commandButton value="Check" action="#{gameBean.check}" />
</a4j:form>
J’ai ajouté :
- l’attribut reRender= »out » dans <a4j:form>
- L’attribut id= »out » dans <h:outputText>
Ce qui tout naturellement veut dire « re-dessiner le composant dans l’identifiant est out à la reception d’une réponse ajax ».
N.B: reRender n’est pas limité à un seul identifiant, et peut prendre une liste d’attributs à re-dessiner, comme par exemple reRender= »out, x, y, z ».
En relançant l’application avec ces modifications, on aura notre guess-game version AJAX !
Pour approfondir la chose, vous pouvez essayer d’ajouter un compteur trials qui indique au fur et à mesure combien d’essaies le joueur a fait + un bouton rejouer qui ne s’affiche que lorsque la réponse est bonne (le second point, je vous le dis d’avance, est un casse-gueule … j’expliquerais pourquoi dans un prochain post).