drik's wiki informatique Languages Le framework Struts

Introduction

Nous allons, durant ce cours, présenter les principales fonctionnalités qu'offre Struts en terme de développement d'application Web. Ce framework fait parti du projet Jakarta du groupe Apache.

L'intérêt principal est d'obtenir une meilleur structuration de votre code. Il en découle donc une meilleur flexibilité ainsi qu'une évolutivité accrue. Il me semble indéniable que ce sont des caractéristiques fondamentales que nous sommes en droit d'attendre d'une application Web d'entreprise.

Ce dernier qualificatif me semble très important : vouloir développer une site Web perso (pour y stocker son CV, par exemple) via le framework Struts relève de la "démence passagère". On n'enfonce pas une punaise via un tank. Il faut relativiser les choses : on ne sort "l'artillerie lourde" que si l'on en attend un bénéfice.

Nous allons donc tâcher d'y voir plus clair, en prenant en main ce framework. Cela nous permettra de ressentir le niveau de complexité de cette architecture afin d'adapter l'utilisation de certaines technologies Web en fonction des besoins. Pour ce faire, nous allons commencer par quelques rappels sur la plate-forme J2EE puis nous parlerons des architectures MVC et MVC 2.

Quelques Rappels sur la plate-forme J2EE

La plate-forme J2EE (Java 2 Enterprise Edition) de Sun Microsystems propose bon nombre de possibilités, via notamment les servlets Java et les pages JSP (Java Server Page). Dans les deux cas, on permet de générer, en dynamique, un contenu HTML dépendant des requêtes précédentes du client ainsi que d'éventuelles informations stockées dans des bases de données. Mais il est vrai que ces deux techniques présentent toutes les deux des inconvénients : en simplifiant les choses, on peut dire que, dans les deux cas, nous n'avons pas de séparation entre le code HTML et le code Java.

Les servlets Java sont des classes Java dérivant d'une classe bien précise (javax.servlet.http.HttpServlet). L'accent est donc mis principalement sur le code. Il va, malgré cela, y avoir dans ce code, des lignes chargées de renvoyer, dans la réponse HTTP, des informations mises en forme via HTML. L'écriture du code HTML, stockée dans des chaînes de caractères Java, en est donc alourdie.

Les pages JSP, au contraire des servlets, mettent l'accent sur le code HTML (une JSP ressemble souvent à une page HTML). Par l'intermédiaire des scriplets, on peut y injecter des blocs de code Java (presque similaires aux blocs de scripts clients – Javascript). Mais le résultat final est souvent similaire à l'approche précédente.

On peut cependant envisager que le développeur cherche à séparer les deux types de code (traitement de la requête et génération du flux HTML). Comme nous l'avons déjà signalé, le gain principal réside dans une meilleure structuration du code et donc une meilleure maintenabilité.

Pour obtenir une telle séparation, on pourrait imaginer d’envoyer les requêtes HTTP vers des servlets Java. Ces servlets (des classes Java, comme nous venons de le voir) ne contiendraient donc que du code "métier" (stockage d'informations, accès aux bases de données, …). Une fois le traitement terminé, chaque servlet pourrait renvoyer l'exécution vers une JSP qui aurait alors à charge de générer le code HTML de retour au navigateur.

Pour partager des informations entre les servlets et les JSP, on pourrait imaginer d’utiliser des composants Java Beans stockés au niveau de la session utilisateur. L'architecture dont nous venons de parler existe : il s'agit du design pattern MVC (Modèle, Vue, Contrôleur).

Les modèles MVC et MVC 2

Une architecture MVC cherche à séparer trois choses : le Modèle, les Vues et les Contrôleurs. Les contrôleurs permettent de répondre aux actions de l'utilisateur. Chaque contrôle est associé à une vue : cette dernière permet de présenter l'information retournée à l'utilisateur. Bien entendu, l'information renvoyée est dépendante des actions d'entrées de l'utilisateur (capturées par les contrôleurs, nous venons de le dire). Les liens (les traitements) sont réalisés par le modèle (la logique métier).

On peut appliquer une architecture MVC à de nombreux cas de mise en œuvre de systèmes informatiques : infographie, applications, … Bien entendu, on peut aussi appliquer cette architecture à la mise en œuvre d'une application Web.

Si nous cherchons à mettre en œuvre une architecture MVC via un environnement J2EE, on peut donc faire les rapprochements suivants :

  • Un contrôleur est implémenté sous forme de servlet Java.
  • Le modèle consiste en l'implémentation de la logique métier du site Web. A ce niveau, l'architecture peut être plus ou moins souple en vous laissant opter pour le type de composants que vous souhaitez utiliser : composants Java Beans ou composants EJB (Enterprise Java Bean).
  • Chaque vue est implémentée via une servlet.

Il est aussi intéressant de noter que dans une équipe de développement de site Web, on peut noter, au moins, deux types d'informaticiens. Les développeurs à proprement parlé : ils ont pour tâche l'implémentation du système. Des servlets et des (E)JB ne devrait donc pas les gêner. Mais, il y aussi les infographistes : ils sont peut-être familiarisés avec HTML ou les feuilles de styles CSS, mais du code Java peut éventuellement les rebuter.

Via ce type d'architectures, chacun intervient donc sur un type de fichier qui lui est familier. Notez en complément, qu'une JSP peut être modifiée sans nécessiter de compilation (bien que l'on puisse réaliser cette étape) : pour un infographiste il est heureux qu'il en soit ainsi.

Dans la pratique, on peut reprocher une chose aux API implémentant un modèle MVC sous environnement J2EE : il est nécessaire de coder un grand nombre de servlets Java pour réceptionner les requêtes clientes. Dans le but d'améliorer ce point, certains frameworks préfèrent implémenter une architecture MVC 2. Dans une telle architecture, il n'existe plus qu'un seul et unique contrôleur réceptionnant toutes les requêtes clientes. Mais comment faire en sorte qu'un unique contrôleur redirige l'exécution, au final, vers différentes vues ? Cela peut être réalisé de manière déclarative, dans un fichier XML, pourquoi pas ?

Il existe un grand nombre de framework basés sur une architecture MVC ou MVC 2. Citons, à titre d'exemple le framework Baraccuda, WebWork, Coccoon … Vous êtes donc en droit de vous poser une question : tel framework est-il mieux que tel autre framework ?

Mais outre les possibilités du système utilisé, il faut souvent aussi considérer sa "durée de vie" et donc sa maintenance. Bon nombre d'entre eux aurons une existence brève et n'intègrerons jamais les évolutions permanentes qu'implique Internet.

A la vue de cet argument, utiliser le framework Struts peut s'avérer être un bon choix. Effectivement, Struts est développé par le groupe Apache. Ce groupe est aussi l'auteur du serveur Web du même nom. En fait, Struts fait partie du projet Jakarta d'Apache.

Installation du framework

Ces concepts étant acquis, il va nous falloir tester les choses. Cependant, avant de passer à cette étape, il nous faut avoir installé Struts. Comme nous allons le voir, l'installation de Struts est un petit peu particulière étant donné que ce framework repose sur l'architecture J2EE (Java 2 Enterprise Edition).

Nous allons donc commencer par faire un bref récapitulatif sur le mécanisme d'installation d'applications J2EE afin de mieux comprendre les étapes nécessaire pour coupler Struts à une application Web.

Structure d'une application Web J2EE

Quelque soit le framework que vous pouvez utiliser, le développement d'applications Web à base de code Java est donc régit par le standard J2EE. Ce standard définit un certain nombre d'aspects et notamment :

  • Un ensemble de services tel qu'un conteneur Web, un conteneur d'EJB, JMS (Java Message Service), JTS, …
  • Un ensemble d'API : elles servent principalement à utiliser les services précédemment cités.
  • Un standard en terme d'empaquetage et de déploiement d'applications WEB J2EE.

C'est ce dernier point qui va nous intéresser dans la suite de ce chapitre. Effectivement, J2EE spécifie l'utilisation d'un certain nombre d'archives Java. Je rappelle, à titre d'information, qu'une archive Java (souvent d'extension .jar, mais aussi .ear, .war, …) est en fait un fichier au format ZIP : vous pouvez donc créer une archive Java, soit via l'outil jar.exe, fournit avec le J2SE, soit via un outil tel que WinZip, ou tout autre équivalent.

L'archive principale d'une application J2EE est l'archive d'entreprise, d'extension .ear (Enterprise ARchive). Cette archive contient normalement l'ensemble de l'application Web prête à être déployée sur un serveur d'applications J2EE quelconque.

Cette archive est constituée de sous-archives et d'un fichier de descripteur de déploiement. Parmi les différentes archives pouvant constituer le fichier .ear, citons notamment :

  • Les archives Web d'extension .war (Web ARchive) : ces archives contiennent tous les fichiers utilisés par la couche de présentation (classes pour les servlets, pages HTML, images, …). Ces archives se déploient sur le conteneur Web du serveur d'applications : l'implémentation la plus connue étant très certainement Tomcat, du groupe Apache.
  • Les archives de composants métiers (extension .jar) : elles contiennent tout le code des EBJ de vos applications.
  • Les archives de ressources (extension .rar).

Dans la suite de ce cours, seules les l'archives Web nous intéresserons. C'est effectivement dans ces archives qu'ils va nous falloir installer le support pour le framework Struts.

Un WAR est une archive : il contient donc lui-même un certain nombre de fichiers et de dossiers. La structure (la hiérarchie) de ces dossiers est en fait fortement imposée, comme le montre le diagramme suivant.

-

Ainsi, votre application Web se doit obligatoirement de contenir un répertoire WEB-INF : c’est dans ce dossier que nous allons trouver le code Java de l'application. Mais encore une fois, des sous-dossiers précis doivent être présents.

Parmi ces dossiers, citons notamment le répertoire classes. Il contient l'ensemble des ".class" utilisés par vos JSP et par vos servlets (notons d'ailleurs que les servlets sont donc logiquement situées à cet endroit). Un autre répertoire important est à signaler : le répertoire lib. Si votre application utilise des librairies additionnelles, c'est ici qu'elles devront être stockées. Vous avez tous compris, Struts verra ses propres ".jar" stockés dans ce dossier.

Intégration de Struts dans une application Web

Il est maintenant le temps de débuter notre installation. Pour ce faire, connectez vous sur le site de Struts (donc sur http://jakarta.apache.org/struts/index.html) et téléchargez l'installation du module Struts. Une fois l'archive sur votre machine, désarchivez-là. Vous devriez y trouver un certain nombres de fichiers d'extensions diverses.

Dans le répertoire qui va contenir votre application Web, créez les différents dossiers dont nous venons de parler précédemment. Nous allons maintenant y ajouter certains fichiers du module Struts.

Copier toutes les archives Java (d'extension .jar) dans le répertoire lib de votre application. A ce stade, tout le code Struts est disponible, mais ce n'est pas tout : une possibilité intéressante de JSP est de pouvoir définir nos propres tags XML : pour ce faire, il faut aussi fournir des fichiers .tld (Tag Library Definition). Struts exploitant cette possibilité, il vous faut donc aussi copier l'ensemble des fichiers d'extension .tld dans le répertoire WEB-INF.

Enfin, il faut définir des descripteurs de déploiement compatible avec J2EE et Struts. Ces fichiers (d'extension .xml) doivent être aussi placés dans le répertoire WEB-INF. Copiez les donc tous. Par contre quelques modifications vont devoir être effectuées sur ces fichiers, et ce, en fonction de vos besoins.

Vérifiez que le contenu du fichier de configuration Struts (struct-config.xml) soit conforme à l'exemple ci-contre. Il est vrai que pour l'heure on y retrouve peu de choses, mais plus tard nous nous devrons d'enrichir le contenu de ce fichier.

    							
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
         "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
         "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
</struts-config>
Fichier "struts-config.xml"

Pour l'heure, il ne nous reste plus qu'à éditer un dernier fichier : web.xml. Ce fichier, spécifié par J2EE, à pour objectif de réaliser un mapping (une correspondance) entre les URLs utilisées et les servlets de votre application Web. On y trouve aussi la déclaration des fichiers de définition de librairie de tag (.tld).


<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC
                 "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN"
                 "http://java.sun.com/dtd/web-app_2_2.dtd">
<web-app>
    <display-name>StrutsWAR</display-name>
    <servlet>
        <servlet-name>action</servlet-name>
        <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
        <init-param>
            <param-name>config</param-name>
            <param-value>/WEB-INF/struts-config.xml</param-value>
        </init-param>
        <init-param>
            <param-name>debug</param-name>
            <param-value>2</param-value>
        </init-param>
        <init-param>
            <param-name>application</param-name>
            <param-value>ApplicationResources</param-value>
        </init-param>
        <load-on-startup>2</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>action</servlet-name>
        <url-pattern>*.do</url-pattern>
    </servlet-mapping>

    <taglib>
        <taglib-uri>/WEB-INF/struts-bean.tld</taglib-uri>
        <taglib-location>/WEB-INF/struts-bean.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>/WEB-INF/struts-html.tld</taglib-uri>
        <taglib-location>/WEB-INF/struts-html.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>/WEB-INF/struts-logic.tld</taglib-uri>
        <taglib-location>/WEB-INF/struts-logic.tld</taglib-location>
    </taglib>
    <taglib>
        <taglib-uri>/WEB-INF/struts-template.tld</taglib-uri>
        <taglib-location>/WEB-INF/struts-template.tld</taglib-location>
    </taglib
</web-app>
Fichier "web.xml"

Struts étant basé sur un architecture MVC 2, un seul contrôleur principal se doit d'être définit. Les auteurs de Struts ont choisis d'implémenter ce contrôleur sous forme de servlet, il va donc falloir configurer cette dernière dans notre descripteur de déploiement.

Le nom de la classe de contrôle de Struts est org.apache.struts.action.ActionServlet. Vous retrouverez dans ce fichier la déclaration de cette servlet qui accepte un certain nombre de paramètres, et notamment le nom du fichier du configuration de Struts (struts-config.xml).

Ensuite, le mapping, à proprement parlé, est réalisé entre les URLs que les clients vont invoquer et notre contrôleur. Du coup, toute les requêtes "struts" se doivent d'être routées vers notre unique contrôleur. Pour ce faire elles auront toutes un point commun : elles se termineront par ".do".

Enfin, le fichier de configuration doit spécifier toutes les définitions de librairies de tags qui seront utilisées par vos servlets. Struts en spécifie quatre principales. Nous reviendrons, ultérieurement dans ce cours, plus en détails sur ces librairies de tags.

Normalement, nous n'aurons plus à éditer ce fichier durant la suite de ce cours. Les futures modifications de configurations impacteront toutes le fichiers "struts-config.xml".

Mise à jour du serveur Web

Notez enfin que si vous utilisez Tomcat comme conteneur d'objets Web (Servlets et JSPs), les choses seront très simples pour ce qui est du déploiement de l'application. Dans le répertoire d'installation de Tomcat, vous devriez y trouver un dossier webapps. C'est dans ce dossier que sont stockées les différentes applications Web hébergées par Tomcat. Copiez-y simplement le dossier de votre application Web.

Les applications Web sont chargées en mémoire au démarrage du serveur. Il est possible via une application Web de gestion de Tomcat d'insérer une application alors que Tomcat est en service. Cette application est accessible via l'url suivante : http://localhost:8080/manager/html.

Malgré cette possibilité, la solution la plus simple est de tomber Tomcat et de le redémarrer. Normalement, l'application Web devrait répondre aux requêtes des utilisateurs.

Concepts généraux

Nous allons voir, dans ce chapitre, les concepts fondamentaux du framework Struts. Effectivement, comme nous allons le constater, ce framework va nous permettre de mieux structurer la mise en œuvre de notre application Web, mais à une condition "sine qua non" : que vous ayez assimilé l'architecture de base de Struts.

Pour ce faire, nous allons procéder en deux étapes. Premièrement, nous allons tâcher de comprendre l'intérêt des concepts fondamentaux (un à un) du framework. Ensuite nous tacherons de mettre en œuvre l'ensemble de ces concepts dans un exemple pratique, afin que vous puissiez voir s'exprimer la puissance de Struts.

Les principaux composants de Struts

Comme nous l'avons déjà dit, lors du chapitre dédié à l'installation du framework struts au sein d'une application Web, la classe servant de contrôleur principal est déjà fournie dans les archives du framework : il s'agit de la classe org.apache.struts.action.ActionServlet. Elle est associée à toutes les requêtes HTTP se terminant par ".do". Nous avons aussi vu que cette servlet accepte un paramètre qui détermine quel fichier de mapping doit être utilisé pour Struts.

Dans ce fichier de configuration, chaque URL est associée à une action : dans la suite de ce document, nous appellerons ces objets d'action, les sous-contrôleurs. Attention, ces objets ne sont pas l'implémentation du modèle. Par contre, ils vont permettre de l'atteindre.

Pour transférer les données du formulaire à l'action, nous allons utiliser une instance dérivée d'ActionForm. L'association entre cette instance, l'URL demandée et l'action est aussi définit dans le fichier de configuration Struts, comme va nous le montrer l'exemple qui suit.

Les vues seront mises en œuvre par l'intermédiaire de JSP. Encore une fois, l'association, l'action et la vue présentant le résultat seront configurés au niveau du fichier de configuration de Struts.

Enfin, pour ce qui est du modèle, le Framework Struts ne vous impose rien et aucune classe ne vous est fournie. Cela vous laisse une totale liberté sur les choix des technologies à utiliser pour l'implémentation du modèle. Ainsi, pour pouvez opter pour un codage basique en implémentant des composants Java standard.

Mais si le besoin s'en fait ressentir, vous pouvez aussi opter pour l'utilisation de composants EJB (Enterprise Java Bean). Ce types de composants métiers permet principalement de dégager le développeur du codage de certains services d'infrastruture : gestion de la persistance des informations, gestion de la sécurité, gestion de transactions logicielles, utilisation de services d'envoie des messages, … Ces services sont fournis par le serveur d'applications qui se configure par l'intermédiaire de descripteurs de déploiement (des fichiers XML).

Il doit être clair que dans ce dernier cas, l'utilisation d'un serveur d'applications complet (et non pas un simple conteneur d'objets Web, tel que Tomcat en version stand alone) devient obligatoire. Citons, par exemple Web Sphere (IBM), JBoss (serveur d'application en licence GPL), WebLogic, …

-
Composants fondamentaux de l'architecture Struts

Le diagramme ci-dessus, reprend, un à un, l'ensemble des points dont nous venons de discuter. Les chiffres affectés aux flèches du diagramme montrent l'enchaînement des exécutions des différentes classes de code Java.

Mise en oeuvre d'un formulaire d'authentification

Afin de mieux comprendre ces différents concepts, une mise en application s'impose. Pour ce faire, nous allons mettre en œuvre une ébauche de site Web, dans lequel un premier formulaire va nous permettre de nous authentifier.

De manière traditionnelle, deux informations seront demandées à l'utilisateur pour prouver son identité : son nom d'utilisateur ainsi que son mot de passe confidentiel. Notons que pour l'heure, le code de validation de l'information renseignée sera réduit à l'extrême : il ne s'agit que d'une présentation des concepts liés au framework Struts. Ne cherchez donc pas de code d'accès à une base de données (si vous désirez allez plus loin, je vous laisse la tâche d'enrichir cet exemple).

Il va donc nous falloir coder un certain nombre de classes et plus précisément, une JSP de saisie, une seconde de confirmation, la classe d'action ainsi que le bean d'ActionForm (pour stocker les informations saisies).

Le formulaire de saisie

Pour la mise en œuvre du formulaire de saisie, nous allons utiliser certains tags proposés par la librairie de tags HTML Struts. Après compilation, ces tags se transformeront en code HTML équivalent et en Javascript. Notez bien que l'utilisation de ces tags pour la définition de la JSP, et non ceux du HTML, est fondamental : les attributs property de tags de saisies permettront le stockage implicite des données dans l'objet FormAction.

    							
<%@ page language="java" import="java.util.*"  %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<html>
    <head>
        <title>Veuillez vous identifier</title>
    </head>
    <body>

        <h1 align="center">Veuillez votre identifier</H1>

        <div align="center">
            <html:form action="login.do" method="POST" focus="username">
                Logon : <html:text property="username" /> <BR/>
                Password : <html:password property="password" /> <BR/>
                <html:submit property="submit" />
	    </html:form>
        </div>
    </body>
</html>

Notons aussi que certains attributs de ces tags (et notamment focus, dans cet exemple) génèrent du script client Javascript afin de palier aux déficiences du HTML. A titre d'information, voici le code HTML que le navigateur reçoit. Tous les tags Struts se sont substitués en code HTML ou Javascript.

Flux HTML/Javascript envoyé au navigateur
<html>
    <head>
        <title>Veuillez vous identifier</title>
    </head>
    <body>
        <h1 align="center">Veuillez vous identifier</H1>
        <div align="center">
            <form name="LoginForm" method="POST"
                 action="/CaddieVirtuel/login.do;jsessionid=9414B6D0FC....">
	  Logon : <input type="text" name="username" value="root"> <BR/>
	  Password : <input type="password" name="password" value="azerty"> <BR/>
                 <input type="submit" name="submit" value="Submit">
            </form>
<script type="text/javascript" language="JavaScript">
  <!--
  var focusControl = document.forms["LoginForm"].elements["username"];

  if (focusControl.type != "hidden") {
     focusControl.focus();
  }
  // -->
</script>
        </div>
    </body>
</html>

Mise en oeuvre du bean de formulaire

Cette classe à donc pour objectif de rassembler les données saisies au niveau du formulaire JSP afin d'exposer ces informations à l'objet d'action ainsi qu'à la vue qui finira par présenter le résultat du traitement. Le formulaire proposant deux champs de saisie (pour le nom d'utilisateur et le mot de passe), notre classe, dérivant d'ActionForm, propose donc deux propriétés : Username et Password. La correspondance entre la JSP et le bean se fait par l'intermédiaire de la réflexion Java.

Le bean de formulaire
    							
import org.apache.struts.action.*;

public class LoginForm extends ActionForm {
	private String m_username = "root";
	private String m_password = "azerty";

	public String getUsername() {
		System.out.println("On passe par UserBean.getUsername !");
		return this.m_username;
	}
	public void setUsername(String username) {
		System.out.println("On passe par UserBean.setUsername !");
		this.m_username = username;
	}
	public String getPassword() {
		System.out.println("On passe par UserBean.getPassword !");
		return this.m_password;
	}
	public void setPassword(String password) {
		System.out.println("On passe par UserBean.setPassword !");
		this.m_password = password;
	}
}

Je rappelle, au cas où, qu'une propriété n'est pas un attribut. Par contre, très souvent (quasiment dans tous les cas) une propriété est associée à un attribut. Dans notre exemple, la propriété Username est associée à l'attribut m_username. Mais alors, qu'est-ce qu'une propriété ? En Java, le codage d'une propriété est régit par la convention de nommage JavaBean : il s'agit en fait d'une paire de méthodes permettant l'accès à l'attribut (les gets et les sets).

Avec l'architecture Struts, l'affectation des valeurs aux propriétés n'est pas de votre ressort. C'est le framework, qui se charge d'initialiser ou de lire les données vers ou à partir de votre Bean. Pour des raisons particulières, nous allons y revenir, votre classe de bean de formulaire se doit obligatoirement de dériver de la classe org.apache.struts.action.ActionForm.

Codage de la classe d'Action

Cette classe d'action va vous permettre de déclencher le traitement de la requête cliente. A cet effet, elle se doit de redéfinir la méthode perform. Le code de cette méthode fera donc appel au modèle. Celui-ci pourra être implémenté avec les technologies de votre choix : soit des composants JavaBeans, soit de EJB. Vous avez donc une certaine souplesse à ce niveau.

Implémentation de la classe d'action
import javax.servlet.http.*;
import org.apache.struts.action.*;

public class LoginAction extends Action {

    public ActionForward perform(
	ActionMapping mapping, ActionForm _form,
	HttpServletRequest request, HttpServletResponse response
    ) throws Exception {
        // On traite la requête cliente
	LoginForm form = (LoginForm) _form;
	System.out.println("Struts in action "
	     + form.getUsername() + " - " + form.getPassword());
        // On redirige vers la vue adaptée
	return mapping.findForward("Connected");
    }
}

Notez bien, et j'insiste, dans cet exemple j'ai simplifié les choses quasiment à l'extrême : on peut dire que pour l'heure, je ne l‘ai pas implémenté. Faîtes aussi attention, au niveau de l'architecture MVC 2 et de Struts, à ne pas confondre le concept de modèle et les objets JavaBeans de stockage des données (les instance ActionForm) : il s'agit de deux aspects complètement différents.

Dans tous les cas, si l'on revient sur la méthode perform, vous noterez qu'elle accepte un certain nombre de paramètres : quatre pour être exact. Je passe les deux derniers : effectivement, pour peu que l'on connaisse le concept de servlets, on sait qu'ils permettent de manipuler la requête HTTP cliente ainsi que la réponse qui lui sera associée. Par contre, les deux premiers sont plus directement liés à Struts.

Le premier, de type ActionMapping, stocke les informations de mapping entre les URLs clientes, les actions, les instances d'ActionForm ainsi que les vues associées. Ces informations sont normalement stockées dans le fichier de configuration Struts (struts-config.xml) : mais comme la lecture d'un document XML n'est pas réellement d'une performance absolue, les développeurs de Struts ont préférés lire ce fichier qu'une seule et unique fois et de stocker les informations qui y sont contenues en mémoire. Et heureusement !

Le second paramètre référence le bean contenant les informations saisies au niveau du formulaire client. Ce paramètre est typé comme étant une ActionForm au niveau de la classe Action. Certes, vous en dérivez, mais comme la liaison dynamique vous implique de respecter le prototype initialement spécifié, vous comprenez donc mieux pourquoi ces beans se doivent de dériver de la classe considérée.

Pour ce qui est du corps de la méthode, rien de bien subtile : je me contente de réaliser des tracés sur la console du conteneur Web (pour ma part Tomcat). Il est clair que selon le conteneur Web utilisé, vous n'aurez pas forcément de console disponible. Dans ce cas là, je vous laisse adapter le code, et pourquoi pas écrire ces informations dans un fichier.

La dernière ligne permet de retrouver la JSP, à partir des informations contenues dans le fichier struts-config.xml, afin de présenter le résultat de la requête HTTP : dit autrement, la vue.

Mise à jour du fichier de configuration

Enfin, voici le fameux fichier struts-config.xml dont nous parlons tant depuis le début de ce chapitre. Si vous l'analysez calmement, on peut dire que les informations qui y sont contenues sont relativement claires. Regardons les choses de plus près.

Le fichier "struts-config.xml"
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
                "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
                "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
	<form-beans>
		<form-bean name="LoginForm" type="LoginForm" />
	</form-beans>

	<global-forwards>
		<forward name="Connected" path="/Connected.jsp" />
	</global-forwards>

	<action-mappings>
		<action	path="/login"
			name="LoginForm"
			type="LoginAction"
			scope="request" >
		</action>
	</action-mappings>
</struts-config>

Une première section permet de nommer les différentes classe de beans ActionForm. Dans notre exemple, les choses sont simples : nous n'avons qu'une unique classe nommée LoginForm. Dans la suite du fichier, cette classe sera utilisable sous un nom, ici, identique. Mais les choses auraient été différentes, si la classe avait été localisée dans un package.

Une seconde section permet de définir les redirections vers les JSP. C'est grâce à cette section que la dernière instruction de la méthode perform de notre classe d'action arrive à localiser la vue à utiliser.

Enfin la dernière section, la plus importante, permet de définir le mapping (un ensemble de correspondances) entre la requête utilisateur et l'action à déclancher. Les paramètres du tag <action> permettent de spécifier ces correspondances.

Le paramètre path permet de définir la requête avec laquelle nous allons travailler. Ensuite, l'attribut name permet de définir l'instance de bean ActionForm à utiliser pour récupérer les informations saisies. Le paramètre type permet, quand à lui, de définir l'action associée.

Le dernier paramètre est aussi très intéressant : il permet d'indiquer la durée de vie souhaitée pour l'objet ActionForm : dans notre exemple, il est demandé à ce que l'objet n'existe que durant le temps de la requête HTTP (valeur "request"). Nous aurions aussi pu choisir la valeur "session" : dans ce cas, les données seraient conservées, pour un utilisateur donné, dans le beans entre les différentes requêtes.

Notez que vous auriez pu fournir un fichier de configuration légèrement différent comme le montre l'exemple de code ci-dessous. Les définitions de redirections introduites par le tag <forward> sont ici définies directement dans l'action et non dans une section <global-forward>. Dans les deux cas, le résultat sera identique.

Une autre manière de spécifier les redirections
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
                "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
                "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
	<form-beans>
		<form-bean name="LoginForm" type="LoginForm" />
	</form-beans>

	<action-mappings>
	        <action	path="/login"
		    	name="LoginForm"
		    	type="LoginAction"
		    	scope="request" >
		    <forward name="Connected" path="/Connected.jsp" />
	        </action>		
	</action-mappings>
</struts-config>

D'autres informations pourraient être renseignées dans ce fichier de configuration, mais pour l'heure nous n'en considérerons pas de supplémentaires.

Le formulaire de confirmation de connexion

L'exemple de JSP proposé ci-contre vous montre comment récupérer les données calculées en résultat de la requête HTTP. Pour ce faire, il nous faut utiliser l'instance d'ActionForm. Celle-ci est accessible dans la JSP via la librairie de tags Struts /WEB-INF/struts-bean.tld. Chaque tag de cette librairie devra être préfixée du namespace bean (exemple : <bean:write>). Notez à ce sujet la manière de lier la librairie à la JSP (seconde ligne dans le code).

La JSP de confirmation de connexion
<%@ page language="java" import="java.util.*"  %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<html>
    <head>
	<title>Confirmation de connexion</title>
    </head>
    <body>
        <h1 align="center">Confirmation de connexion</H1>

        <div align="center">
	        Bonjour Mr <bean:write name="LoginForm" property="username" />
        </div>

    </body>
</html>

La récupération se fait donc via le tag <bean:write>. Ce bean est de type LoginForm et expose donc deux propriétés (username et password). Dans l'exemple, nous décidons de récupérer le nom d'utilisateur et de l'injecter dans le flux HTML.

Tests du formulaire de connexion

Il ne nous reste plus qu'à tester notre formulaire de saisie. Mais attention, si vous avez déjà lancé votre serveur Web, le code que nous venons d'adjoindre ne sera pas pris en compte. Il faut donc redémarrer l'application Web. Deux techniques sont envisageables pour arriver à vos fins.

La première technique consiste à stopper, et à relancer le serveur Web. Cela aura pour effet de permettre le chargement du code associé à notre formulaire. Cela ne sera pas la technique la plus rapide.

La seconde technique consiste à utiliser la console d'administration de votre serveur Web (en l'occurrence, pour nous Tomcat). Deux sous-alternatives vous seront normalement accessibles. Soit vous déploierez l'application sur le serveur (à chaud : sans le redémarrer), soit si celle-ci est déjà installée, vous la rechargerez. Pour obtenir la console d'administration de Tomcat, saisissez simplement l'URL http://localhost:8080/manager/html dans votre navigateur. Et oui, cette console est en fait une application Web déployée sur Tomcat.

Vous pouvez maintenant invoquer votre formulaire via cette seconde URL : http://localhost:8080/CaddieVirtuel/Login.jsp (pour peu que votre application soit située dans un répertoire CaddieVirtuel.

Validation de formulaire

Un des problèmes classique à gérer, si vous fournissez des formulaires Web, consiste à valider que les données nécessaire ont bien été renseignées. Le framework Struts propose, dans cet objectif, des mécanismes directement intégrés dans l'architecture de base.

A partir de là, pouvez soit choisir d'exploiter ces fonctionnalités, soit de passer outre et pourquoi pas d'utiliser vos propres mécanismes de validation. Il me semble que cela serait dommage. Nous allons donc, dans ce chapitre, voir les concepts fondamentaux liés aux mécanismes de validation de formulaires Struts.

Support de validation de la classe ActionForm

La classe ActionForm définie aussi une méthode validate : à ce niveau, le corps de cette méthode est vide. Celle-ci accepte deux paramètres comme le montre l'exemple ci-dessous. Le framework Struts invoque automatiquement cette méthode après avoir chargé les données du formulaire dans le bean, mais avant l'invocation de la méthode perform. En fait, la méthode perform ne sera invoquée que et uniquement que si la méthode de validation ne détecte aucune erreur dans la saisie du formulaire.

Afin de définir vos propres tests de validations, il vous faut donc redéfinir cette méthode au niveau de votre classe de bean de formulaire : respectez bien le prototype définit au niveau de la classe mère. Si lors de vos tests vous détectez des erreurs, une collection (typé via la classe ActionErrors) vous permettra de passer les messages d'erreurs à la JSP qui retournera le flux HTML au navigateur. Vous pourrez donc ainsi y injecter les dits messages d'erreurs.

Pour valider notre formulaire d'authentification, quelques tests préliminaires peuvent être réalisés. Notez que nous pourrions validez les informations saisies au niveau d'une bases de données : une table pourrait y contenir l'ensemble des comptes utilisateurs définis. Ce n'est pas ce que nous allons chercher à faire ici : ce type de code devrait plutôt se trouver au niveau de l'action associée à la requête.

Pour l'heure nous allons simplement chercher à voir si les deux champs ont au moins été renseignés. Si ce n'est pas le cas, il n'est pas nécessaire de redonner la main à l'objet d'action : autant retourner directement sur le formulaire de saisie, ce jusqu'à que nos deux informations aient bien été fournies.

Implémention de la méthode de validation
public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
	ActionErrors errors = new ActionErrors();

	if (this.getUsername() == null || this.getUsername().equals("")) {
		errors.add("username", new ActionError("Veuillez saisir un login"));
		System.out.println("Error : bad username");
	}

	if (this.getPassword() == null || this.getPassword().equals("")) {
		errors.add(
		    "password",
		    new ActionError("Veuillez saisir un mot de passe")
		);
		System.out.println("Error : bad password");
	}

	return errors;
}

Si l'une des deux zones de saisies est donc mal renseignée, nous ajoutons à la collection d'erreurs un objet d'erreur par l'intermédiaire de la méthode add. Quand la méthode validate se termine, la main est redonnée à Struts. Celui-ci examine la collection d'erreurs est si, au moins, une entrée existe, le traitement sera détourné vers une JSP de traitement de l'erreur. Dans notre cas, cette JSP sera simplement notre formulaire de saisie.

Modification du fichier de configuration

Outre le code de validation, il faut aussi fournir quelques informations supplémentaires au niveau du fichier de configuration Struts (strust-config.xml) pour pouvoir autoriser la validation d'un formulaire. Revenons sur la déclaration de l'action. En plus des paramètres précédemment étudiés, il nous faut rajouter les paramètres validate et input.

Modification du fichier "Struts-config.xml"
<action-mappings>
	<action	path="/login"
		name="LoginForm"
		type="LoginAction"
		input="/Login.jsp"
		validate="true">
	</action>
</action-mapping>

Le paramètre validate peut recevoir les valeurs true et false. Je pense que vous avez tout compris, il permet effectivement d'autoriser la validation Struts ou non. Si vous y passez la valeur false, la méthode validate ne sera donc pas invoquée.

Le second paramètre, input, permet de spécifier quelle est la JSP vers laquelle rediriger en cas d'erreur dans la saisie. Notez encore une fois, que dans notre cas, il s'agit du formulaire de saisie.

Implementation du modèle

Comme nous l'avons déjà signalé, l'implémentation du modèle (pour notre architecture MVC 2) vous est laissée libre. Vous avez donc le choix entre deux techniques : soit utiliser des composants Java Beans, soit utiliser des composants EJB. Ces derniers points, relativement techniques, sortent du cadre de ce cours.

Afin d'y voir plus clair sur les possibilités offertes par l'intégration avec le reste de l'architecture Struts, nous allons continuer la mise en œuvre de notre application Web. Comme son nom l'indique, vous l'aurez compris, nous allons chercher à mettre en place un caddie virtuel. Pour l'heure, nous allons chercher à voir comment permettre à l'utilisateur de visualiser les articles proposés par le site.

Normalement, une base de données aurait été la bien venue pour stocker, de manière persistante, les articles considérés. Pour des raisons de simplicité, nous allons faire une croix sur la base et travailler avec un simple tableau d'article qui sera construit au démarrage de l'application.

Nos classes métiers

Deux classes vont nous permettre d'implémenter notre couche métier : la classe Article et la classe Catalog. La première, la classe Article, permet de représenter un article au sein de notre vitrine électronique. Quatre attributs vont nous servir : un identifiant unique, une marque, une désignation et enfin, un prix.

Bien entendu, pour être un bean, la classe doit embarquer les méthodes d'accès aux attributs : les propriétés. Quelques tests sont réalisés sur les méthodes d'accès en écriture au cas ou des données incohérentes serait fournies.

Une classe d'article
public class Article {          // Un bon vieux Java Bean bien classique

    private int m_IdArticle;
    private String m_Marque;
    private String m_Designation;
    private double m_Price;

    public int getIdArticle() { return this.m_IdArticle; }
    public void setIdArticle(int idArticle) throws Exception {
	if (idArticle<0) throw new Exception("IdArticle must be positive");
	this.m_IdArticle = idArticle;
    }

    public String getMarque() { return this.m_Marque; }
    public void setMarque(String marque) {
	this.m_Marque = marque.toUpperCase();
    }

    public String getDesignation() { return this.m_Designation; }
    public void setDesignation(String designation) {
        this.m_Designation = designation.toLowerCase(); 
    }

    public double getPrice() { return this.m_Price; }
    public void setPrice(double price) throws Exception {
	if (price<0) throw new Exception("Price must be positive");
	this.m_Price = price;
    }

    public Article() throws Exception {
	this(0, "Inconnue", "???", 1);
    }

    public Article(int id, String marque, String designation, double price)
	    throws Exception {
	this.setIdArticle(id);
	this.setMarque(marque);
	this.setDesignation(designation);
	this.setPrice(price);
    }

    public String toString() {
       return this.m_IdArticle + ": article "
            + this.m_Designation + " de marque "
            + this.m_Marque + " et de prix "
            + this.m_Price + " Euros";
    }
}

Deux constructeurs sont fournis afin de permettre l'instanciation de la classe. Jusque là rien de nouveau. Et enfin, la méthode toString permet de générer une chaîne de caractères identifiant l'objet.

Implémentation simpliste d'un catalogue d'articles
// Cette implémentation de catalogue d'articles est très simpliste,
// je vous l'accorde. Mais le but consiste à vous montrer certains concepts
// fondamentaux de Struts. Je ne préfère donc pas alourdir le reste du code !!!

public class Catalog {
    public static Article [] m_Articles = new Article[4];

    static {
	try {
	    m_Articles[0] = new Article(0, "Byque", "Stylo bleu", 1);
	    m_Articles[1] = new Article(1, "FoncéFontaine", "Ramette papier", 5);
	    m_Articles[2] = new Article(2, "Harry beau", "bonbon", 0.2);
	    m_Articles[3] = new Article(3, "Bidule", "Equerre", 3);
	} catch(Exception e) {
            System.err.println("Ouille !");
        }
    }

}

Cette seconde classe permet donc de définir un ensemble d'article que les utilisateurs vont pouvoir sélectionner. Comme ce catalogue est partagé entre les différents utilisateurs, le fait de spécifier le tableau comme étant static nous posera aucun problème.

Il est vrai que nous pourrions envisager de récupérer les articles à partir des données stockées dans une base de données. Je vous laisse, en exercice, le soin d'adapter le code si vous souhaitez pousser cet exemple. Dans tous les cas, le code Struts à mettre en œuvre sera similaire.

Implémentation de l'action

Notre classe d'action est en fait relativement simple. Via le bean de formulaire, on obtient l'identifiant de l'article à retourner à la vue. Il ne nous reste donc plus qu'à localiser l'article considéré dans notre catalogue d'articles (le modèle). Pour simplifier la récupération, au sein de la vue, de l'article on le stocke dans le bean de formulaire.

		
import javax.servlet.http.*;
import org.apache.struts.action.*;

public class ChooseAction extends Action {

    public ActionForward execute(
        ActionMapping mapping, ActionForm _form,
        HttpServletRequest request, HttpServletResponse response
    ) throws Exception {
        ChooseForm form = (ChooseForm) _form;
        form.setArticle( Catalog.m_Articles[form.getIdArticle()] );
        System.out.println( form.getArticle() );
        return mapping.findForward("Choose");
    }

}
La classe d'action

Au final, on repart vers la vue, qui n'est autre que le formulaire de sélection d'article. La redirection est encore opérée via la méthode findForward de l'objet de mapping (de correspondance d'URL). Notez que juste avant cette redirection, un affichage est réalisé sur la console du serveur, via la méthode toString (appel implicite) de notre article.

Une autre solution, pour partager des données entre l'objet d'action et la vue, aurait consisté à enregistrer le bean au sein de la requête HTTP. Ainsi, la vue pourrait récupérer l'instance de bean ultérieurement.

Mise en place de la vue

Enfin, la vue présente l'information sélectionnée. L'affichage de l'article se fait par l'intermédiaire du tag <bean:write>, comme le montre l'exemple ci-dessous. Notez la différence d'utilisation entre les deux premières utilisations du bean.

<%@ page language="java" import="java.util.*"  %>
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<html>
    <head>
	<title>Veuillez Choisir vos articles</title>
    </head>
    <body>

        <h1 align="center">Veuillez Choisir vos articles</H1>

	<div align="center">
	    Id de l'article :
		<bean:write name="ChooseForm" property="idArticle" /> <BR/>
	    Marque :
		<bean:write name="ChooseForm" property="article.marque" /> <BR/>
	    Designation :
		<bean:write name="ChooseForm" property="article.designation"/> <BR/>
	    Prix unitaire :
		<bean:write name="ChooseForm" property="article.price" /> <BR />

	    <%
	        int idArticle = Integer.parseInt(request.getParameter("idArticle"));
	    %> <BR />
	    <a href="choose.do?idArticle=<%= idArticle - 1 %>">Précédent</a> - 
	    <a href="choose.do?idArticle=<%= idArticle + 1 %>">Suivant</a>
	</div>
    </body>
</html>
Implémentation de la vue

La première ligne utilise la propriété idArticle du bean de formulaire : la syntaxe est donc relativement simple. Par contre, la ligne injectant la marque est un petit peu plus subtile : nous cherchons à retrouver la valeur de la propriété marque de l'article contenu dans le bean de formulaire. Pour ce faire une syntaxe simple permet d'exprimer la chose. L'attribut property="article.marque" réalise la liaison. Pour les deux autres caractéristiques de l'article, il en va de même que pour la marque.

Notez aussi le mécanisme utilisé pour réaliser la navigation entre les différents articles du catalogue. On incrémente, ou l'on décrémente l'identifiant passé en paramètre de l'URL.

Mise à jour du fichier de configuration

Bien entendu, avant de tester votre JSP de navigation, il vous faudra mettre à jour le fichier de configuration struts-config.xml afin de définir une nouvelle action associée à la demande de présentation d'un article particulier. Modifiez le dit fichier de manière à ce qu'il corresponde au code suivant.

            					
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts-config PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 1.1//EN"
    "http://jakarta.apache.org/struts/dtds/struts-config_1_1.dtd">
<struts-config>
	<form-beans>
		<form-bean name="LoginForm" type="LoginForm" />
		<form-bean name="ChooseForm" type="ChooseForm" />
	</form-beans>

	<global-forwards>
		<forward name="Connected" path="/Connected.jsp" />
		<forward name="Choose" path="/ChooseArticle.jsp" />
	</global-forwards>

	<action-mappings>
		<action	path="/login"
			name="LoginForm"
			type="LoginAction"
			scope="request" />

		<action path="/choose"
			name="ChooseForm"
			type="ChooseAction"
			scope="request" />
	</action-mappings>
</struts-config>

Le fichier "struts-config.xml"

Internationalisation via Struts

Outre la mise en œuvre d'une architecture MVC, Struts permet aussi de prendre en charge l'internationalisation de vos applications Web. Cela signifie que vous avez à votre disposition un mécanisme simple permettant de générer un contenu adapté à la localisation de l'utilisateur. Notez aussi, à ce sujet, qu'il n'y a pas que les textes qui peuvent être amenés à changer d'une langue à une autre. Les images aussi peuvent varier. Effectivement, si l'on considère une image associée au concept de mails : les français préféreront voir une petite lettre alors que les américains reprendront la symbolique de boîte à lettre. Mais, si l'on y réfléchit, vis-à-vis du tag <IMG> c'est le contenu du paramètre src qui devra varier : donc une chaîne de caractères.

La mise en œuvre de l'internationalisation passe par la définition de fichiers de ressources. Chacun des fichiers sera associé à une langue particulière : cette information se retrouvera dans le nom du fichier. Tous les noms de fichiers de ressources devront avoir le même préfixe. Celui-ci est spécifié dans le fichier web.xml (le descripteur de déploiement du War) sous forme de paramètre de la servlet de contrôle. Les noms se continuent avec un caractère _ puis le code de la langue (codé sur deux caractères) et enfin ils se terminent via l'extension .properties.

Définition des fichiers de ressources

Ces fichiers de ressources se doivent d'être placés dans le répertoire classes de votre application Web pour pouvoir être pris en charge par le serveur. Ils contiennent, comme leur nom l'indique, des ressources : en fait il s'agit de paires de données clé/valeur. Dans votre programme, vous référencerez les clés afin d'injecter les valeurs associées.

Dans l'exemple ci-dessous, deux fichiers de ressources sont définis. Ils sont, certes, très simplistes : une seule ressource est définie dans chaque fichier. Mais notez bien que la clé est identique d'un fichier à un autre.

Définition des fichiers de ressources
Fichier "ApplicationResources.properties"
CaddieVirtuel.Test.Title=Virtual Caddy
Fichier "ApplicationResources_fr.properties"
CaddieVirtuel.Test.Title=Caddie Virtuel

Le premier fichier est celui qui sera pris par défaut : son nom n'a pas d'information relative à la langue considérée. Par contre le second sera utilisé dans le cas ou il faudrait générer un contenu en langue française.

Rappels sur le descripteur de déploiement du WAR

A titre d'information, je vous rappelle comment notre servlet de contrôle est définie au sein du descripteur de déploiement du WAR : le fichier "web.xml". Notez la présence du paramètre application qui indique la base des noms de fichiers de ressources.

            					
<servlet>
    <servlet-name>action</servlet-name>
    <servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
    <init-param>
        <param-name>config</param-name>
        <param-value>/WEB-INF/struts-config.xml</param-value>
    </init-param>
    <init-param>
        <param-name>debug</param-name>
        <param-value>2</param-value>
    </init-param>
    <init-param>
        <param-name>application</param-name>
        <param-value>ApplicationResources</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

Utilisation des ressources

Le framework Struts définit plusieurs possibilités d'utilisation de ces ressources. Citons notamment l'emploie du tag <bean:message> définit dans la librairie /WEB-INF/struts-bean.tld. Ce tag injecte la valeur associée à une clé donnée : vous spécifiez la clé recherchée par l'intermédiaire de l'attribut key.

            					
<html:html locale="true">
    <!-- Suite de la page -->
    Injection d'une valeur : <bean:message key="searchKey" />
    <!-- Suite de la page -->
</html:html>

Notez enfin que pour qu'une JSP supporte les mécanismes d'internationalisation, il faut le spécifier afin que les bon fichiers de ressources puisse être sélectionnés. Pour ce faire il nous faut utiliser le tag <html:html> fournit dans la librairie de tags /WEB-INF/struts-bean.tld. Ce tag accepte notamment un paramètre locale. Fixez lui la valeur true afin d'autoriser l'internationalisation.

Autres concepsts Struts

La bibliothèque de tags struts-logic

Cette librairie de tags permet principalement d'obtenir des structures de contrôles au sein des JSP. Vous pouvez ainsi exécuter des boucles, pour mettre en forme des ensembles de données, exécuter des conditions et de tester des expressions régulières.

L'exemple ci-dessous vous montre comment présenter un ensemble de données sous forme de tableau HTML. Pour ce faire, nous utilisons le tag Struts <logic:iterate>. Ce tag accepte quelques attributs. Citons notamment name qui permet de retrouver un bean à partir de la requête et property qui permet de dire qu'elle est la propriété qui retourne la collection d'éléments à traiter. Le code HTML compris entre les tags <logic:iterate> et </logic:iterate> sera répété autant de fois qu'il y aura d'objets dans la collection.

            					
<table width="100%" border="1">
	<tr>
		<th>Identifiant article</th>
		<th>Désignation</th>
		<th>Marque</th>
		<th>Prix unitaire</th>
	</tr>
	<logic:iterate id="myLoop" name="CaddyForm" property="articles">
	   <tr>
		<td><bean:write name="myLoop" property="idArticle" /></td>
		<td><bean:write name="myLoop" property="designation" /></td>
		<td><bean:write name="myLoop" property="marque" /></td>
		<td><bean:write name="myLoop" property="price" /></td>
	   </tr>
	</logic:iterate>
</table>

Dans ce second exemple, une ligne de code HTML ne sera injectée dans le flux HTML que si la propriété age (donc accessible via l'invocation de la méthode getAge) d'un bean nommé User, est supérieur à 17 ans. Dans le cas contraire, rien ne sera injecté dans le flux.

            					
<logic:greaterThan name="User" property="age" value="17">
		<B>Vous êtes majeurs</B>
</logic:greaterThan>

La bibliothèque struts-layout

La plate-forme J2EE permet donc de définir des tags supplémentaires que vos JSP vont pouvoir utiliser. C'est une des choses que fait principalement le framework Struts avec ses librairies de tags. D'autres groupes de travails sont repartis sur ce concept pour enrichir le framework Struts avec des librairies de tags supplémentaires. Il en existe un certain nombre qui sont, plus ou moins, intéressants.

Parmi ces projets, citons notamment Struts Layout. Celui-ci propose de nombreux tags supplémentaires. Les principales possibilités sont : améliorations des contrôles de saisies au sein d'un formulaire, grille d'affichage de données (avec support de pagination), tags de génération d'onglets Web, utilisation d'arborescences Web, …

L'ajout de Struts Layout au sein de votre application Web est similaire à l'installation de Struts. Reportez-vous au chapitre considéré pour de plus amples informations à ce sujet.

Exemple d'utilisation de struts-layout

L'exemple ci-dessous met en place une grille affichant une collection d'articles (j'ai réutilisé la classe Article précédemment étudiée). Cette JSP (cette vue) est bien entendu affichée après avoir exécuté une action Struts. Au sein de cette action, un tableau (Java) d'instances d'articles à été généré. Puis ce tableau à été sauvegardé dans la requête (via la méthode HttpRequest.setAttribute) sous le nom Articles.

 

La JSP utilise donc des tags Struts et notamment le tag <layout:collection>. Ce tag permet de localiser le tableau dans l'objet de requête HTTP et d'en afficher son contenu. J'ai de plus cherché à paginer les résultats par blocs de 5 (il est souhaitable que le tableau d'articles en contienne plus d'une dizaine). Pour ce faire, j'utilise le tag <layout:pager>.

La capture d'écran qui suit vous montre, à titre d'exemple, le rendu HTML de la JSP ainsi définie (la feuille de styles utilisée, ainsi que les images, sont proposés par Struts Layout). Pour de plus amples informations sur Struts Layout, je vous laisse consulter le site officiel : http://struts.application-servers.com.

-
struts, framework, informatique, languages, wiki, drik, formulaire, implementation, validation, internationalisation, installation, introduction, concepsts, generaux, concepts, modele, autres, mise, configuration, fichier, jour, bibliotheque, application, ressources, rappels, utilisation, connexion, classe, action, layout, oeuvre, authentification, modification, descripteur, integration, deploiement, definition, composants, actionform, principaux, structure, quelques, fichiers, modeles, classes, serveur, support, metiers, forme, plate, logic, tests, place, tags, dans, confirmation, exemple, codage, saisie, bean