Date de première publication : 2012/05/24
Objectif et contexte
L'objectif de cet exercice est de créer une petite application JSF qui utilise de l'AJAX sous Glassfish. On pourrait modifier la devinette du nombre mais nous allons nous intéresser à un carnet d'adresse.
- Java SE 8
- Java EE 8
- Netbeans 8.3
- Glassfish 4+
- Mojarra (JSF) 2+
Site sans AJAX
Créer un nouveau projet Netbeans :
- Projet : Java Web / Web application
- Nom : CarnetAJAX
- Serveur d'applications : Glassfish Server / Java EE 7 Web
- Framework : cocher JavaServer Faces (JSF 2.2 avec Facelets par défaut)
Créer une classe Java Personne
toute simple ! (pas un bean)
Créer un nouveau bean managé CarnetBean
(de portée "scope" : Session
par exemple). Ce bean va simuler l'interaction avec le carnet d'adresse en créant quelques instances d'une classe Personne
(nom, prenom, telephone, mail, notes).
Ce bean managé est de type JSF Managed Bean
Le bean contiendra, entre autres, un attribut personnes
, une liste de Personne
.
@ManagedBean
@SessionScoped
public class CarnetBean {
List<Personne> personnes;
// ...
}
Le constructeur initialise une liste non vide.
Première version du site
On va essayer d'afficher la liste des personnes dans un tableau (après tout ce sont des données tabulaires) dans la page index.xhtml en ne précisant que les noms et prénoms et un clic sur une petite icône va ouvrir une nouvelle page avec tous les détails sur cette personne.
Pour afficher un tableau, on a besoin des balises :
<table>
<thead>
<th> <td> </td> <td> </td> </th>
</thead>
<tbody>
<tr> <td> </td> <td> </td> </tr>
</tbody>
</table>
Un boucle se déclare facilement en JSF : <c:forEach>
et les attributs var
et items
.
Si l'on veut appliquer facilement un style sur les lignes (par exemple une ligne sur deux), on peut définir et modifier une variable avec <c:set>
<c:set var="i" scope="view" value="1" />
<c:set var="i" value="#{(i+1)%2}" />
Les balises <commandLink>
et <graphicsImage>
permettent de finaliser le lien avec la deuxième page qui contient la description, page qu'il faut également créer. La page affiche les détails d'une personne que le bean mémorise.
Une version un peu plus JSF
Nous avons déjà obtenu une page relativement potable avec les balises de la JSTL, mais, en fait, on peut mieux faire. JSF propose une balise <h:dataTable>
capable de faire ce que l'on a fait avec les attributs var
et value
.
Les balises <h:column>
et <f:facet>
permettent respectivement de déclarer les colonnes et leur titre. On peut également appliquer des styles aux différents éléments générés :
<h:dataTable value="#{carnetBean.getPersonnes()}" var="p"
rowClasses="line1,line0"
styleClass="general"
headerClass="header">
<h:column><f:facet name="header">Nom</f:facet>#{p.getNom()}</h:column>
</h:dataTable>
Ça a l'air quand même plus simple, non ?
Une pincée d'AJAX
On va maintenant passer à l'AJAX qui est intégré depuis la norme 2.0 de JSF (chargement automatique d'une bibliothèque javascript lors de l'utilisation du tag). Le résultat à l'écran sera le suivant : une zone de la page affichera les détails de la personne et non plus une nouvelle page.
Pour intégrer de l'AJAX, il suffit d'ajouter la balise <f:ajax>
sur les actions que l'on générait auparavant et de spécifier ce que l'on veut faire par exemple en donnant les informations suivantes :
render
: composant(s) à mettre à jour après l'appel AJAXexecute
: composant à exécuter lors de l'appel AJAX, Cela peut être@form
si l'on veut exécuter tous les composants du formulaire
Les composants sont repérés par les identifiants (id
) et suivant l'endroit où ils sont, les noms peuvent être compliqués. L'utilisation des deux points (:
) devant un id permet de spécifier que le nom de l'élément est donné en absolu.
h:outputText
permet de générer un span, il nous faut générer un div en précisant obligatoirement le layout et l'id
<h:panelGroup layout="block" id="" />
Si vous utilisez au mauvais endroit la propritété render
, sachez que vous pouvez avoir l'erreur :
malformedXML :during update : XXX id not found
. La raison en est très simple : l'interface étant exécutée du côté vue (client), il faut que l'id soit connu pour être modifié, ce qui n'est pas le cas si le composant n'est pas affiché. La solution : imbriquer des panelGroup
par exemple.
Dernière remarque, nous avions choisi une durée de vie (portée) pour le bean lié à la session (SessionScope
), c'était pratique pour changer de page. On peut maintenant se restreindre au niveau de la vue (ViewScoped
) car on ne change plus de page.
Prochaine étape : intégrer la persistance avec JPA