Java Server Faces (JSF) versus WebForms par sami jaber (jaber@ifrance.com)

Introduction

127 est le chiffre de la dernière JSR (Java Specification Requests) de Sun qui n'a pas fini de faire couler beaucoup d'encres. DotNetGuru attendait les premiers résultats de cette JSR de pied ferme pour plusieurs raisons. Tout d'abord, les WebForms de Microsoft n'avaient jusqu'à présent aucun véritable concurrent utilisant une infrastructure de présentation similaire. Les JSP ne sont en aucune manière ce challenger tant attendu car leur application s'arrête à la génération simple de pages dynamiques. Quant aux outils de plus haut niveau tels que Struts, Webwork ou encore Jade, ils se rapprochent plus de Framework MVC que de véritables modèles évènementiels. Il faut bien l'avouer, jusqu'à présent, Microsoft régnait en maître incontesté sur ce marché émergent avec son concept de WebForms.

L'annonce de la spécification Java Server Faces (JSF) a donc sonné comme un avertissement pour Microsoft qui voit son leadership mis à mal par cette nouvelle norme concurrente. JSF se positionne en concurrent direct des WebForms en proposant un modèle évènementiel basé sur la notion de composants graphiques réutilisables en JSP. 

Au delà de l'annonce même d'une telle initiative, Microsoft et Sun nous conduisent tout deux vers une nouvelle ère dans le développement d'applications Internet. Le temps où les pages HTML étaient générées manuellement à l'aide de code script mélangé à du HTML est révolu, place à la création d'applications Web basées sur un vrai modèle de programmation évènementiel et structuré.

Cet article se propose donc de vous faire un bref aperçu des différentes caractéristiques de Java Faces comparées aux WebForms de Microsoft. JSF étant encore en phase de Draft, il y a fort à parier qu'à l'avenir, des évolutions viennent enrichir la spécification actuelle rendant ainsi obsolète certaines assertions de cet article. 

Pourquoi un tel Framework ?  

A l'heure où les pages deviennent de plus en plus complexes, le modèle qui consiste à générer manuellement les pages HTML sous la forme de flux de caractères est bel et bien dépassé. En effet, ce type d'approche a clairement montré ses limites car elle impose en règle générale aux concepteurs de pages la maîtrise de plusieurs métiers différents. Les graphistes se doivent de comprendre la logique applicative (langages de script) utilisée à l'intérieur des pages. Et les développeurs sont contraint de maîtriser l'art de la création graphique en HTML.

Si les outils sont essentiellement destinés à masquer la complexité sous-jacente des pages HTML, ils peinent à tenir ce rôle car leur fonctionnement repose essentiellement sur un socle (HTML, HTTP) non structuré.  Une page est vue comme un flux d'octets et non comme un modèle de composants graphiques hiérarchiques de type WinFoms ou Swing

Pourtant, à bien y regarder, la logique est similaire. Un acteur déclenche des évènements sur une interface graphique composée de contrôles et le Framework propose un socle permettant d'accéder aux différents composants du formulaire à l'intérieur de ces mêmes évènements. C'est d'ailleurs ce qui fait dire à certains que les WebForms font office de Visual Basic du Web. Cette remarque, souvent prise au sens péjoratif du terme tend à faire croire que les WebForms sont un modèle RAD "quick and dirty" alors qu'ils s'attachent à structurer fortement les développements.

Voyons ce que propose Microsoft dans ce domaine.

Les WebForms  

Comme nous l'avons vu précédemment, les WebForms ont été créé par Microsoft pour pallier le manque de structuration dans le développement des applications Web. 

Les WebForms ont donc pour principale tâche de transposer le modèle de développement d'une application client lourde classique vers un environnement Internet. Le protocole HTTP étant sans état, l'opération n'est pas des plus simples. Il est nécessaire de prendre en compte les valeurs postées entre chaque validation de formulaire afin de notifier l'utilisateur lorsqu'un contrôle est modifié depuis son dernier rendu. 

Cette chaîne de responsabilités, relativement complexe à mettre en oeuvre, est représentée par "le cycle de vie" d'une page. Le rôle d'un Framework tel que WebForms consiste à assurer l'ensemble de ces opérations de manière totalement transparente pour l'utilisateur. 

Le cycle de vie d'un WebForm

Les WebForms respectent donc les étapes suivantes :

1. Création d'une représentation mémoire de la page et création de l'arbre des contrôles ou "Control Tree"

2. et 3. Chargement du flux de la requête HTTP et association des valeurs aux contrôles conformément au ViewState

4. Chargement de la page et déclenchement des évènements 

5. et 6. PreRendu permettant une dernière fois à l'utilisateur de modifier la ControlTree et le ViewState avant l'exécution du Rendu final

Dans cet article, nous n'entrerons pas dans le détail de ces différentes étapes, sachez cependant qu'il est nécessaire de bien saisir leur rôle respectif dans le cycle de vie général d'une page.  

Java Server Faces (JSF)

Présentation 

Java Server Faces est un Framework pour la conception d'interfaces graphiques Web en Java. JSF s'attache donc à :

Plus généralement, JSF établit une norme par le biais d'API dont le rôle est de fournir aux développeurs une large palette d'outils leur permettant d'implémenter des applications HTML en respectant un modèle bien précis.

Au delà de cet aspect, JSF prend en compte plusieurs types de profils de développeur. Tout d'abord, les développeurs non expérimentés appelés encore "corporate developer". Ces développeurs sont des personnes familiarisées avec l'approche procédurale et évènementielle. Ils n'ont à priori aucune connaissance en programmation orientée objet et seront les plus à même à utiliser les outils ou assistants graphiques fournis par des tiers.

Les développeurs expérimentés ou "System programmers", eux, représentent une catégorie de développeurs initiés aux techniques de programmation objet et comprenant parfaitement les mécanismes internes du Framework JSF. Ceux là seront moins enclin à utiliser les assistants et autres outils d'aide à la conception. Jusqu'à aujourd'hui, les "corporate developer" étaient les principaux laissés pour compte dans le développement d'applications Web Java car ils se devaient de maîtriser un minimum le Framework de présentation mis en place. Aujourd'hui la spécification JSF tente d'apporter une solution à ces personnes.

Résoudre les problèmes classiques du Web

JSF a été conçu pour être indépendant des protocoles (HTTP) et langages de représentation (HTML). A ce titre, il est destiné à résoudre tous les problèmes inhérents à la programmation Web habituelle. Il assure donc :

Nous retrouvons ici les mêmes concepts généraux énoncés dans le Framework graphique de Microsoft. Voyons plus en détail le cycle de vie d'une page. 

Le cycle de vie d'une page JSF

Le cycle de vie d'une page JSF est décrit dans la figure suivante. La première fois qu'une page dynamique est affichée sur le poste du client, le processeur JSF construit un arbre de contrôles coté serveur sur le même principe que les WebForms. 

Cet arbre est constitué de l'ensemble des widgets utilisées par les formulaires HTML (simples ou complexes) et constitue le modèle de référence sur lequel les développeurs s'appuieront pour modifier le rendu d'une page. L'exemple suivant nous illustre le mode de fonctionnement d'une page HTML après transformation opérée par le processeur JSF.

Lors de la validation du formulaire, le serveur reconstitue l'arbre des contrôles et stocke les valeurs de la "Requête" (Request) dans chaque composant graphique. L'opération suivante consiste à parcourir l'arbre des contrôles afin de détecter une éventuelle modification. Pour ce faire, le serveur compare les valeurs actuelles de chaque composant à celles mémorisées dans la session de l'utilisateur à l'instant t-1. Cela signifie donc que les JSF, contrairement aux WebForms gèrent la persistance des contrôles suivant un mode stateful.

En cas de modification, un évènement est déclenché automatiquement par le Framework et l'utilisateur a la possibilité de le gérer afin d'interagir directement avec l'arbre des contrôles. La dernière étape consiste à mettre à jour le modèle de présentation et à générer la réponse HTML en fonction de la hiérarchie des composants. Cette opération s'appelle le Rendu ou "Rendering".

Les schéma suivant illustre le cycle de vie d'une page JSF :

Toutes ces étapes permettent de reproduire le fameux modèle évènementiel. Jusqu'ici, vous vous interrogez peut-être sur les différences existantes entre WebForms et JSF. Patience, nous y arrivons. 

Un exemple simple avec WebForms et Java Faces

L'application suivante est basée sur un exemple fourni dans le package JSF de Sun : Cardemo. L'utilisateur sélectionne des voitures et après avoir saisi leurs options, effectue un achat en ligne. Nous allons nous intéresser uniquement à la page ci-dessous présentant une voiture avec sa description détaillée. 

Cette page comprend trois contrôles. Le premier est le titre de la voiture représenté par un label. Le second constitue la description du véhicule et le troisième contrôle est un bouton de soumission "More". 

Pour implémenter cette page en JSP, vous ne pourrez compter sur aucun outil pour la simple et bonne raison que la spécification Java Server Faces n'en est encore qu'à sa phase de revue (bêta ou public review). Elle doit donc être soumise à validation avant d'atteindre sa maturité. C'est pourquoi, il vous nécessaire de saisir manuellement le code source suivant dans un éditeur de texte simple :

<HTML>
     
<HEAD>
           
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
           
<TITLE>Welcome to CarDemo</TITLE>
     
</HEAD>
     
<%@ taglib uri="http://java.sun.com/jstl/fmt" prefix="fmt" %>
     
<%@ taglib uri="http://java.sun.com/j2ee/html_basic/" prefix="faces" %>
     
<BODY BGCOLOR="white">
           
<fmt:setBundle basename="carDemo.Resources" scope="session" var="carDemoBundle" />
           
<jsp:useBean id="CarServer" class="cardemo.CarServer" scope="session" />
           
<jsp:useBean id="CurrentOptionServer" class="cardemo.CurrentOptionServer" scope="session" />

           
<faces:usefaces>
                 
<faces:form id="/carStoreForm" formName="carStoreForm" modelReference="${CurrentOptionServer}">

                       
<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="6" WIDTH="660" BGCOLOR="white" ID="Table3">
                             
<TR>
                                  
<TD WIDTH="50%" VALIGN="TOP"><IMG SRC="car.gif">
                                       
<faces:output_text 
                                            id
="
/carStoreForm/car1title"
                                           
modelReference="${CarServer.car1Title}" 
                                           
key="car1title" />

                                              
</FONT></B><FONT FACE="Arial, Helvetica">
                                              
<BR>
                                              
<BR>
                                        
<faces:output_text 
                                              
id="
/carStoreForm/car1Desc" 
                                               modelReference
="${CarServer.car1Desc}"
                                              
key="car1Desc" />

                                              
<BR>
                                        
</FONT>
                                        
<faces:command_button 
                                           
id="
/carStoreForm/more1" 
                                            label
="More" 
                                            key
="moreButton" 
                                            commandName
="more1" />

                                  
</TD>
                             
</TR>
                       
</TABLE>
                 
</faces:form>
           
</faces:usefaces>

     
</BODY>
</
HTML>

Voici le même exemple utilisant les WebForms. Cette fois ci, Visual Studio (ou WebMatrix) nous permettent de concevoir de manière graphique notre interface.  

Une fois l'opération réalisée, regardons le source généré par l'outil :

<%@ Page language="c#" Codebehind="WebForm1.aspx.cs" AutoEventWireup="false" Inherits="WebApplication13.WebForm1" %>
<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" >
<
HTML>
     
<HEAD>
           
<title>CarDemo</title>
     
</HEAD>
     
<body MS_POSITIONING="GridLayout">
           
<form id="Form1" method="post" runat="server">
                 
<IMG style="Z-INDEX: 101; LEFT: 57px; WIDTH: 204px; POSITION: absolute; TOP: 49px; HEIGHT: 154px"
height="154" src="../tomcat4.0/webapps/cardemo/pictures/crop_compact_small.gif" width="204" align="left" border="0">

                 
<asp:Label  id="Label1" 
                                  
style="Z-INDEX: 102; LEFT: 63px; POSITION: absolute; TOP: 209px"
                                   runat="server" 
                                  
Width="455px" 
                                  
Height="59px">

                 
If you're the type who doesn't care what anyone thinks, this is the car for you. 
                 
Strictly for "point-a-to-point-b" types</asp:Label>

                 
<asp:Label id="Label2" 

                                  
style="Z-INDEX: 104; LEFT: 286px; POSITION: absolute;TOP: 56px"                                    runat="server">Duke's Stripped-Down Jalopy </asp:Label>


                 
<asp:Button id="Button1" 

                                  
style="Z-INDEX: 103; LEFT: 67px; POSITION: absolute; TOP: 292px" 
                                  
runat="server" Text="More" />


           
</form>
     
</body>

</
HTML>

WebForm1.aspx 

JSF respecte un modèle plus orienté "objet"

Si la démarche générale parait très proche, la ressemblance la plus frappante provient de la présence des contrôles serveurs. Là où ASP.NET utilise le formalisme asp:controlname, JSF utilise une TagLib faces:controlname. La comparaison s'arrête là car les différences sont profondes entre ces deux pages. Tout d'abord, JSF impose au développeur beaucoup plus de contraintes que WebForms qui adopte une écriture plus concise et moins "verbeuse". 

Ensuite, chaque page JSF doit disposer d'un ordre use-bean indiquant qu'un JavaBean est utilisé au chargement de la page. Ce bean doit être configuré dans le scope de la Session utilisateur. Cela signifie que toute page JSF est associée à un modèle objet dont les attributs représentent les différents champs du formulaire. C'est ce qu'il convient d'appeler le "modèle de présentation" (ModelReference) de la page. Comme vous pouvez le constater sur le fichier suivant, les méthodes du modèle correspondent bien au contenu des champs de la page WebForm1.aspx. On retrouve ici un mode de fonctionnement très proche des Framework MVC. Le JavaBean constituant le modèle.

Par ailleurs, un nommage très particulier est utilisé pour associer les contrôles serveur au modèle de présentation. L'ordre "${CarServer.car1Title}" signifie que la valeur du contrôle doit être insérée dans la propriété car1Title de l'objet CarServer identifié par l'attribut Key

C'est une des différences fondamentales avec les WebForms dont les contrôles prennent leur source dans des collections de type DataSource (énumérable). En d'autre terme, là où JSF contraint à passer par des JavaBean pour stocker la persistance des informations de page, WebForms nécessite simplement l'usage d'une collection ou d'une valeur donnée. Les DataSource peuvent être alimentés à l'aide de DataSet représentant des objets .NET sérialisés en XML. L'approche "objet" de JSF peut-être donc être reproduite avec les WebForms en passant par une classe intermédiaire dont les attributs correspondraient aux différents champs du formulaire. Il s'avère qu'en pratique, bon nombre de développeurs WebForms font appel à des curseurs de type base de données (ResultSet ou DataReader) pour alimenter leurs contrôles graphiques. Nous déconseillons fortement cette démarche car elle nuit à l'indépendance des couches. 

Avantages et Inconvénients 

L'inconvénient de la démarche orientée "modèle de présentation" réside dans la représentation systématique de chaque page à l'aide de JavaBeans. Si nos données sont stockées dans une base quelconque, il sera nécessaire de réaliser deux opérations :

  1. Extraire les données des tables ou d'un modèle de données quelconque (Persistance DAO, EJB, JDO, ....)

  2. Insérer ces données dans le modèle de présentation (ModelReference)

Un "mapping" doit donc être mis en place pour assurer la correspondance entre modèle de données et modèle de présentation. Il existe certains cas où ce mode de fonctionnement peut s'avérer coûteux. Typiquement lorsque le modèle de présentation (les formulaires HTML) est parfaitement équivalent au modèle de données (la base), par exemple lors de l'affichage basique d'une simple table, la plus value de cette démarche est faible. 

Toutefois, lorsque modèles de données et modèles de présentation présentent des différences importantes, cette démarche a l'avantage de simplifier l'écriture des pages car chaque formulaire dépend d'un seul et unique modèle de référence. 

Au final, les WebForms et les JSF utilisent tout deux une approche très semblable au niveau de la persistance des contrôles de formulaire mais diffèrent dans leur implémentation respective. 

La gestion des conteneurs de contrôles 

lorsqu'on aborde pour la première fois l'exemple CarDemo présent dans l'implémentation de référence de JSF, on est frappé par la complexité des pages JSP au regard des fonctionnalités fournies par le Framework. C'est d'ailleurs un des premiers reproches exprimés par la communauté Java à l'égard de la norme dans sa version actuelle. Sans compter la pauvreté du catalogue de contrôles proposés. Les spécifications font état aujourd'hui de quelques composants de base de type TextBox, Label ou SelectItem qui s'avèrent très vite limités dans le cas d'applications complexes. Attardons nous un instant sur CarDemo.

L'exemple précédent a volontairement été simplifié pour afficher un seul élément du catalogue de voitures. Dans sa version originale, l'application CarDemo gère une liste de voiture avec chaque description répétée autant de fois que de voitures. Non seulement, les contrôles Label1 et Label2 et le Button "More" sont répétés autant de fois que de lignes, mais la gestion des évènements liés à ces contrôles est totalement rédhibitoire. Et pour cause, voici le source du gestionnaire d'évènement relatif à la page d'accueil. Nous reviendrons plus en détail sur la gestion des évènements dans les parties suivantes. 

if (facesEvent instanceof FormEvent) 
{
 
FormEvent formEvent = (FormEvent) facesEvent;

if
(formEvent.getCommandName().equals("more1")) {
        optServer.setCarId(1);
    }
      
    else
if (formEvent.getCommandName().equals("more2")) 
    {
        optServer.setCarId(2);
        
    }

   
else if (formEvent.getCommandName().equals("more3")) {
       
optServer.setCarId(3);
       
    }
            
    else
if (formEvent.getCommandName().equals("more4")) 
    {
        optServer.setCarId(4);
       
    }

 (etc...)
    else if (formEvent.getCommandName().equals("customer")) 
    {
        // Business logic
    }

returnValue = false;
}

Avec cet exemple, on met le doigt sur toute la difficulté d'un Framework de présentation. Il ne s'agit pas simplement de proposer à l'utilisateur des contrôles basiques de type TextBox, Label, RadioButtons, etc... Mais encore faut-il que ce Framework fournisse des contrôles de type conteneur tels que des Listes, DataGrid,Calendriers ... Ces derniers jouent un rôle fondamental car ils contiennent des contrôles fils représentant éventuellement des conteneurs de contrôles. JSF nous propose une liste de contrôles basiques et l'utilisateur les traite de manière totalement indépendants l'un de l'autre. Cette approche s'avère très vite limitée lorsqu'il s'agit de concevoir un DataGrid contenant dans chaque cellule un autre DataGrid contenant elles-mêmes des contrôles basiques. Bref, toutes les caractéristiques d'une page riche.

Voyons ce que propose les WebForms pour résoudre ce type de problème.  

<asp:datalist id="DataList1" runat="server" OnItemCommand="DataList_ItemCommand" GridLines="Both">
     
<HeaderTemplate>
               
Car Catalog
     
</HeaderTemplate>

      <ItemTemplate>
           
<asp:image id="Image1" runat="server" />
           
<asp:Label id="Label1" runat="server">Car Title</asp:Label>
           
<asp:Label id="Label2" runat="server">Car Description</asp:Label>
           
<asp:Button id="button1" runat="server" Text="More" CommandName="select" />
           
<%# DataBinder.Eval(Container.DataItem, "StringValue") %>
     
</ItemTemplate>

</
asp:datalist>

Non seulement le code précédent est simple et efficace mais le conteneur de contrôle est géré de manière assez élégante avec un contrôle conteneur ; le DataList. Pour vous en convaincre, il suffit simplement de le comparer à son équivalent JSF.

Par ailleurs, les WebForms proposent une abstraction totale de la présentation sous la forme de modèles (Template) alors que les JSF adopte une gestion manuelle de l'affichage via du code HTML. 

Quant aux évènements, vous avez la possibilité de les attribuer en fonction de chaque contrôle fils ou directement en passant par le contrôle parent, en l'occurrence le DataList. Cela permet de traiter les évènements de manière local et lorsque vous êtes dans la n-ème ligne de votre liste, de récupérer le contexte lié à la ligne courante. Cette démarche épargne au développeur l'opération de localisation pour rechercher le contrôle ayant été activé dans la collection.

Il faut bien l'avouer, les WebForms ont réellement été étudiés pour proposer une abstraction totale du Framework de présentation et alléger le travail du développeur par l'emploi de différents types de contrôles adaptés à chaque besoin. Charge ensuite à l'utilisateur de choisir les bons ingrédients telle une recette de cuisine.

Quant aux JSF, ils imposent non seulement plus de contraintes techniques, mais ils se basent toujours sur une gestion manuelle de l'affichage en proposant simplement une librairie de TagLibs. On était en droit de s'attendre à mieux.

Enfin, nous vous passons les détails sur les WebForms permettant de remonter des évènements dans les contrôles parent (EventBubbling) afin d'éviter le morcellement des évènements. Un chef d'oeuvre du genre ! 

Accéder à l'arbre des contrôles (Control Tree) 

Lorsque la page HTML est chargée, l'utilisateur dispose d'un arbre de contrôles lui permettant à tout moment de modifier une valeur ou une propriété en passant par un modèle purement objet. La page n'est plus vue comme un ensemble de tags HTML mais comme une représentation hiérarchique. La spécification DOM (Document Object Model) constitue également un type de modèle arborescent de pages HTML pouvant être utilisé, mais son utilisation ne permet pas réellement de gérer la notion de contrôles serveur. C'est pourquoi la plupart des Framework proposent une structure interne de type Tree pour JSF et Page Template pour les WebForms.

Si l'arbre des contrôles existe de part et d'autres, voyons quelles sont les API proposées pour y accéder. Le listing ci-dessous vous illustre la récupération d'un composants DropDownList1 situé dans un DataGrid :

protected void Product_Update(object sender, DataGridCommandEventArgs e)
           
{
                 
//get the current product name
                 
string pname=e.Item.Cell[1].Controls[0].Text;
                 
//get the current product price
                 
string price=e.Item.Cell[2].Controls[0].Text;
                 
//get the current categoryid
                 
DropDownList ddl=(DropDownList)e.Item.Cells[3].FindControl("DropDownList1");
                 
string categoryid=ddl.SelectedItem.Value;
                 
//get the current productid
                 
string pid=e.Item.Cell[4].Controls[0].Text; 
                 
//call pdb's update function
                 
pdb.update(pid,pname,price,categoryid);

           
}
Product.aspx.cs

Voici l'écriture se rapprochant le plus de l'exemple précédent en Java Server Faces  :

       // findComponent accepte un nommage de type File System
        UISelectItems ddl= (UISelectItems) faceEvent.getComponent().findComponent("/form1/SelectList1");        
           

Encore une fois, la différence fondamentale entre les deux approches se situe au niveau de l'implémentation. Alors que WebForms permet à l'utilisateur de modifier directement l'arbre des contrôles, JSF impose au développeur de passer par le modèle objet sous-jacent (BeanForm). 

En résumé, dans les deux Frameworks, la représentation de l'arbre est équivalente mais la sémantique diffère. JSF reste attaché au modèle objet alors que WebForms permet de modifier directement l'arbre des contrôles sans aucune contrainte particulière.

La gestion du rendu  

Le Rendu consiste à générer le flux de réponse HTML une fois l'arbre des contrôles finalisé. WebForms et JSF utilisent tous les deux un parcours récursif de l'arbre consistant à invoquer la méthode Render() de chaque élément. Cette approche est strictement la même dans les deux environnements avec la possibilité pour un élément donné de contrôler l'affichage de ses fils. Ainsi, un DataGrid souhaitant prendre en charge le rendu de ses cellules devra inhiber l'appel récursif à la méthode Render().

 

 

La fonction de Rendu joue un rôle important dans la cible multi-clients. Par exemple, dans le cas d'un client de type téléphone portable, le rendu devra s'opérer en WML. Aujourd'hui, seuls les WebForms gèrent cette fonctionnalité à l'aide du Mobile Toolkit. Les JSF se contentent de l'intégrer dans la spécification sans réellement définir un cadre d'utilisation strict. 

La création des contrôles utilisateur 

Quel outil peut se prétendre être un Framework de présentation s'il ne permet pas à l'utilisateur d'implémenter ses propres contrôles ? 

Cet aspect est primordial même si la marge de manoeuvre avec HTML est très étroite. Rappelez-vous, le langage HTML utilise des composants standards dont l'aspect visuel et le comportement sont difficilement modifiables. Malgré cela, l'intérêt de développer ses propres contrôles réside dans la réutilisation qui peut en être faite. Notre formulaire précédent contenant quelques contrôles simples aurait bien pu constituer un exemple de Custom Control. En pratique, tout dans une application Web peut prétendre à être un contrôle réutilisable. C'est le rôle du Framework de vous proposer ce socle. 

Alors que nous nous attendions avec JSF à une API standard basée sur le concept de TagLib, la déception a été grande lorsque nous avons parcouru les quelques pages de la spécification. Pas un seul mot,  pas une seule phrase à ce sujet. La création de contrôles a tout simplement été occultée. De ce fait, on comprend mieux pourquoi certains composants tels que les DataGrid, les DataList ou autres Calendrier n'ont pu être implémentés dans la RI (Reference Implementation) et sont passés sous silence. Sun ne peut compter sur des éditeurs tiers pour développer ce type de contrôles car cela reviendrait à adopter une démarche propriétaire.

JSF est peut-être encore en gestation et la charge de travail restant à fournir est considérable, mais nous avons réellement été déçu par cette partie de la spécification ...

Quant aux WebForms, la création d'un composant utilisateur est assez triviale et les API sont d'une rare richesse. De la gestion de l'affichage à l'association des données (DataBinding), tout y est pour permettre au développeur de laisser court à son imagination. Sans compter la souplesse apportée par la gestion des évènements. Bref, nous aurions pu vous illustrer tout ceci à travers un exemple simple mais en l'absence de challenger, cela n'a que peu d'intérêt. Si d'aventure le sujet vous intéresse, sachez que cette démarche est illustrée dans un ouvrage entier (de 300 pages) dédié aux Contrôles Serveur WebForms : ASP.NET Server Controls (chez wrox).

La gestion des évènements

Avec JSF

JSF propose deux types d'évènements :

- Les évènements de requêtes.

- Les  évènements d'application.

Officiellement, la spécification indique que les évènements de requêtes sont déclenchés lorsque l'utilisateur sélectionne un contrôle donné ne faisant pas appel à une nouvelle page. Ces évènements sont totalement occultés dans la spécification ainsi que dans le tutorial de Sun. "These kinds of events are not documented for this release". 

Les évènements d'application provoquent le chargement d'une nouvelle page. Ces évènements sont aujourd'hui regroupés en deux familles : les évènements  de type Command et Form

Pour traiter les évènements d'application dans JSF,  l'utilisateur doit explicitement implémenter l'interface ApplicationHander. Cette classe définit quelle page doit être appelée lorsqu'un évènement se produit. Pour ceux parmi vous maîtrisant le modèle de développement MVC, on retrouve ici la vue appelée par le contrôleur suite à une mise à jour du modèle. 

Quant à l'enregistrement de la méthode dans le Framework, nous vous en faisons grâce tellement cette opération est d'une effroyable complexité. A ce sujet, la spécification indique que les prochaines versions de JSF s'attacheront à simplifier ce modèle. C'est à espérer. 

Avec les WebForms

La gestion des évènements dans les WebForms est un délice pour peu que l'utilisateur soit un minimum familiarisé avec le Framework. Chaque contrôle possède un type d'évènement respectant la signature suivante Handler(sender, EventArgs). Pour associer un évènement à un contrôle, rien de plus simple : 

Un double click sur le bouton en question provoque instantanément la création de l'évènement suivant :

      private void Button1_Click(object sender, System.EventArgs e)
           
{ // implémentation de l'évènement   }

Au delà même de ce mode de fonctionnement somme toute basique, l'architecture WebForms est batie sur un socle lui permettant de répercuter tout changement opéré dans les contrôles à travers la méthode RaisePostBackEvent(). L'utilisateur a la possibilité à tout moment de modifier ce comportement ou d'implémenter des évènements personnalisés. Imaginez une TextBox contenant une valeur de cours de bourse. En cas de changement dans la zone de texte, l'évènement levé par défaut est TextChanged. Rien de vous empêche de modifier cet évènement afin de le rendre plus compréhensible sous un nouveau type StockChanged

Bref, la gestion des évènements de JSF est incomparable à celle des WebForms. Le but de cet article n'étant pas de vous énumérer les multiples qualités (que nous connaissons déjà) du Framework de Microsoft. Nous nous arrêterons donc là. 

La gestion des erreurs et les validateurs (validators)

Les validateurs constituent un des apports les plus importants d'un Framework de Présentation. Leur rôle consiste à assurer la gestion des contraintes dans les champs de formulaires. Cette gestion peut s'opérer soit coté client (JavaScript) soit coté serveur et doit être paramétrable.
Dans ce domaine, WebForms et JSF adoptent le même mécanisme consistant à faire appel aux TagLibs. JSF utilise "<face:validator>" et WebForms "<asp:Validator>".

<td valign="top">
      
 <faces:textentry_input id="middleInitial" size="1" maxLength="1" 

           
modelReference="${CustomerBean.middleInitial}" > 
           
<faces:validator 

                      
className="javax.faces.validator.StringRangeValidator"/>
            
     <faces:attribute 

                        
name="javax.faces.validator.StringRangeValidator.MINIMUM"
                        
value="A"/>
            
     <faces:attribute 

                        
name="javax.faces.validator.StringRangeValidator.MAXIMUM"
                         
value="z"/>
       
</faces:textentry_input>

       
<faces:validation_message componentId="middleInitial"/>
       
<br>

</
td>

Voici le même exemple en WebForms :

<td valign="top">
      
<asp:TextBox id="TextBox1" style="Z-INDEX: 102; LEFT: 377px; POSITION: absolute; TOP: 88px" runat="server"></asp:TextBox>
      
<asp:RangeValidator 
                   
id="rangeValInteger"
                   
Type="Integer" 
                    ControlToValidate
="TextBox1"
                   
MaximumValue="10" 
                    MinimumValue
="1"
                   
runat="server" />

</td>

Vous aurez remarqué la ressemblance existante entre les deux codes sources.  D'une manière générale, l'approche est similaire excepté le fait que JSF ne propose aucun paramétrage des validateurs en mode Javascript coté client. Gageons que cette fonctionnalité sera présente dans les prochaines versions. 

Conclusion

Il faut bien l'avouer, nous nous attendions à mieux de la part du groupe de travail JSR 127 constitué de gourous Java tels que Craig R. McClanahan. Nous aurions tant voulu vous dire que JSF était un des Framework Java de l'année et que le trône détenu par les WebForms allait se mettre à vaciller. Au lieu de cela, nous avons droit à une spécification et une implémentation de référence (RI) bâclées, incomplètes et sans aucune mesure avec le Framework de Microsoft. Les WebForms ont indéniablement pris une avance considérable sur le standard JSF et il faudra s'armer de patience pour espérer voir un jour des Pages JSF conçues dans  Eclipse à l'aide d'un Plug-In JSF WYISWYG. Qui sait, l'avenir nous réservera peut-être de bonnes surprises cette fois...


Auteur : Sami JABER

Copyright : DotNetGuru © Septembre 2002

 

Ressources

Le site officiel de Java Server Faces : http://java.sun.com/j2ee/javaserverfaces/index.html

Les spécifications de Java Server Faces : http://java.sun.com/j2ee/javaserverfaces/download.html

Java Server  Faces RI (Implémentation de référence compatible Tomcat) : http://developer.java.sun.com/developer/earlyAccess/j2ee/javaserverfaces/index.html

Le Tutorial en ligne de Java Server Faces  :  http://java.sun.com/j2ee/javaserverfaces/docs/tutorial.html