Accueil > Le langage JSP et les Servlets Java > Apprentissage du framework Struts Jakarta - Partie 2

Apprentissage du framework Struts Jakarta - Partie 2

Par Sue Spielman, 31/10/2001

Traduit par Thierry, 05/09/2002

Voici la deuxième partie de la série à trois épisodes consacrées au framework Struts. Dans la première partie, Introduction au Jakarta Struts Framework, j’ai défini ce qu’était le framework Struts, j’ai parlé de ce qu’il pouvait accomplir et j’ai effectué un survol des divers composants utilisés. Dans cet article, je décrit les différentes phases de construction d’une petite application simple en partant de zéro et en se servant de Struts 1.0. Le troisième article vous montrera comment utiliser les balises Struts pour accéder au fichier ApplicationResource à partir d’un JSP.

Cette aproche étape par étape devrait vous éclairer d’avantage et vous montrer le potentiel de l’utilisation de Struts dans vos développements d’applications. Si vous n’êtes pas familier de la technologie Struts, jetez d’abord un oeil à l’article d’introduction.

Cet article suppose que vous ayez l’expérience des JSP, des Servlets, des Librairies de balises personnalisées et de XML. De plus, j’utiliserai un certain nombre de projets Jakarta tout au long de cet article, à savoir Tomcat 3.2.1, le container de servlet utilisé dans l’implémentation de référence officielle des Servlets Java et des technologies JSP (la plus récente version, la 3.2.3, implémente quelques corrections de problèmes de sécurité de la 3.2.1), et Ant, un outil de construction basé sur Java.

En tant que développeur ayant écrit des centaines d’applications en utilisant des technologies de pointe (et habituellement saignantes), je crois fermement en la compréhension de la logique d’évolution des nouvelles technologies. Alors qu’il est possible de se contenter de plonger dedans et d’apprendre au fur et à mesure (ce dont nous sommes tous coupables), j’aimerais profiter de cette opportunité pour parcourir la démarche typique d’un développement basé sur Struts. J’appliquerai cette démarche à notre échantillon d’application, mais vous serez capable d’appliquer ces étapes à des scénarios plus importants et plus compliqués. J’ai moi même appliqué cette démarche sur de grands projets et elle est a prouvé qu’elle était adaptée.

Quiconque a écrit une application business ou Web sait que la liste des besoins est toujours quelque peu dynamique; le fait de s’en tenir à une démarche de développement vous aidera au moins à identifier quelles tâches supplémentaires devront être ajoutées à la liste. Voyons en détail la démarche, puis je vous l’expliquerai et l’appliquerai à notre petite application.

Tout au long de cet article, j’utiliserai des extraits de code de l’application StrutsSample. Le code complet, y compris le fichier build.xml pour construire et déployer l’application, est disponible en téléchargement ici.

Cycle de développement Struts

Comme vous pouvez le remarquer par le n° de version, Struts est relativement récent. Il y a de nombreux composants qui travaillent de concert, mais savoir à quel moment compléter tel ou tel composant peut vous économiser pas mal de temps, sans parler de votre santé d’esprit. J’ai écrit de nombreuses applications basées sur Struts, et j’ai trouvé que suivre une approche similaire à celle-là était efficace :

  1. Rassembler et définisser les besoins de l’application.
  2. Définissez et développez chaque écran en termes de données saisies ou affichées.
  3. Déterminez le mode d’accès à chaque écran.
  4. Définissez les ActionMappings (cartographie des actions) qui se rapportent à la logique business de l’application.
  5. Développez les classes ou API qui sont nécessaires pour répondre aux besoins des écrans.
  6. Créez les ActionForms (formulaires action) avec des propriétés définies par les besoins écrans (pouvant inclure aussi les parties de validation).
  7. Développez les Actions à appeler par les ActionMappings, qui à leur tour appellent les helpers appropriés et font suivre aux JSPs.
  8. Développez la logique business de l’application (Beans, EJB, etc).
  9. Créez les JSP correspondant aux distributions de tâches basées sur les ActionMappings.
  10. Construisez les fichiers appropriés de configuration — struts-config.xml, web.xml.
  11. Développer/tester/déployer.

Rassembler et définisser les besoins de l’application

La première étape de tout développement d’application consiste en la collecte des besoins. Bien que cela puisse sembler logique, c’est souvent plus dure qu’il n’y paraît. Le fait d’être en possesion d’un ensemble de besoins écrits n’est pas seulement important pour les objectifs de développement, mais aussi pour mettre en évidence les endroits nécessitant de plus amples définitions.

Les besoins de l’application de notre projet StrutsSample sont les suivants :

Prodiguer une petite application autorisant la connexion d’un utilisateur dans le but de faire la démonstration d’une progession logique complète basée sur le framework Struts. N’allourdissez pas l’application de notions en rapport avec la sécurité, l’interaction avec les bases de données, le développement d’EJB ou tout autre technologie auxiliaire qui pourrait être utilisée dans une application plus complexe.

Définissez et développez chaque écran en termes de données saisies ou affichées

Cette application sera composée de trois écrans :

  • Un écran de connexion autorisant la saisie d’un nom d’utilisateur et d’un mot de passe.
  • Une page d’accueil qui confirme le succès de la connexion en affichant le nom de l’utilisateur.
  • Une page d’erreur indiquant que l’identification a échoué.

Déterminez le mode d’accès à chaque écran

  • La page de connexion sera la page affichée par défaut.
  • La page d’accueil ne sera accédée que sur une identification correcte de l’utilisateur.
  • La page d’erreur sera accédée à partir de toute page pouvant générer une erreur.

Définissez les ActionMappings qui se rapportent à la logique business de l’application

De manière basique, les ActionMappings représentent la carte routière de l’application. Les ActionMappings définissent tous les évènements pouvant survenir dans une application. Les ActionMappings sont définies dans le fichier struts-config.xml et fonctionnent par redistribution de manière à fournir les flux de l’application.

Habituellement, vous accumulez les informations relatives à l’ActionMapping, telles que le nom de formulaire ou la donnée en entrée, au fur et à mesure que vous développez. De manière primaire, cette étape de développement a pour but de former les hommes de pail au fichier struts-config.xml. La redirection d’une action indique ce qui va se passer au moment où la classe action retourne un des MappingForwards définis. Il est tout à fait possible d’avoir plusieurs redirections pour une action. Chaque classe action peut définir des redirections spécifiques qui sont pertinentes pour cette classe. Gardez aussi à l’esprit qu’il est possible d’avoir des redirections globales. Représentez vous cela sous forme de fichier include pour chaque action. Si une redirection retournée par une classe action n’est pas spécifique à l’ActionMapping mais est définie comme étant une redirection globale, alors la définition globale sera utilisée. Les redirections locales peuvent toujours être utilisées pour surpasser les redirections globales. Dans notre exemple, ci-dessous, si une erreur est retournée par une action, alors Errorpage.jsp sera affichée, même si cette redirection n’est spécifique à aucune action.

Vous verrez au fur et à mesure que vous progesserez dans vos développements que ce fichier de configuration peut devenir assez détaillé pour de grands projets. Dans l’exemple ci-dessous, extrait du fichier struts-config.xml du StrutsSample, nous pouvons voir des définitions de redirections globales et l’échantillon d’une cartographie d’actions. Cette cartographie définit une action appelée “login” qui est une instance de la classe com.oreilly.actions.LoginAction. Après une identification correcte la redirection “success” affichera Welcome.jsp. Si une redirection de type “failure” survient, Login.jsp sera réaffiché. Si une redirection de type “error” est retournée, alors la redirection globale sera utilisée et affichera Errorpage.jsp

<!-- ========== Définitions des redirections globales -->
<global-forwards>
<forward name="login" path="/Login.jsp"/>
<forward name="error" path="/Errorpage.jsp"/>
</global-forwards>

<!-- ========== Définitions des action-mappings -->
<action-mappings>
<!-- Attributs de l'élément <action> -->
<!--
Pour d'autres attributs possibles voir org.apache.struts.action.ActionMapping
dans les JavaDocs
path - Le chemin URI de la requête chargée de sélectionner ce mapping.
type - Nom complet de la classe Java d'implémentation de l'Action utilisée par ce mapping.
name - Nom du bean formulaire défini dans le fichier config que cette action utilisera.
unknown - Positionné à vrai si cette action doit être configurée comme action par défaut
pour gérer toutes les requêtes non gérées par une autre action. Une seule action peut
être définie comme action par défaut pour une application donnée.
scope - Identifiant du périmètre ("request" ou "session") à l'intérieur duquel le bean
formulaire, s'il y en a un, associé à cette action sera créé.
input - Chemin d'accès fonction du contexte du formulaire de saisie auquel il faudra
donner le contrôle si une erreur de validation est rencontrée.
validate - Positionné à vrai si la méthode validate() de l'action associée à ce mapping
doit être appelée.
forward elements - L'ensemble des ActionForwards localement associés à ce mapping.
-->

<!-- =================== -->
<!-- O'Reilly Struts Sample Main Actions -->
<!-- =================== -->
<action path="/login"
type="com.oreilly.actions.LoginAction"
name="loginForm"
scope="request"
input="/Login.jsp">
<forward name="success" path="/Welcome.jsp"/>
<forward name="failure" path="/Login.jsp"/>
</action>
</action-mappings>

Comme nous l’avons déjà vu dans le premier article, struts-config.xml est le contrôleur principal au sein du modèle MVC. Il mérite que l’on passe sur lui pas mal de temps de développement pour s’assurer que les actions répondent correctement aux besoins de l’application. Une fois que toutes les pièces sont montées, vous souhaiterez éviter une situation dans laquelle vous auriez à réorganiser complètement vos actions à cause de définitions insuffisamment détaillées en début de projet.

Notre application StrutsSample ne nécessite qu’une seule action — la connexion. En fonction de la taille de votre application, il peut y avoir beaucoup plus d’actions requises et définies. Une fois que les ActionMappings sont définis, vous pouvez les examiner une à une et commencer à rassembler les classes d’ActionMapping et de formulaires.

Développez les classes ou API qui sont nécessaires pour répondre aux besoins écrans

Toutes les classes formulaires dans Struts sont une extension de org.apache.struts.action.ActionForm. La classe formulaire est utilisée pour établir la correspondance avec les champs de données d’un écran. La classe formulaire peut aussi être utilisée pour la validation des champs de saisie. Les méthodes accessor Setter/Getter (NDT : méthodes qui permettent de modifier/obtenir les valeurs des variables d’instance d’un objet) sont appelées automatiquement au moment de la soumission d’un formulaire HTML (submit), étant de ce fait disponibles pour de futures utilisations par la classe action. Habituellement, une classe ActionForm gère toutes les variables d’un formulaire, et contient la phase nécessaire de validation d’un écran donné. J’ai tendance à maintenir toutes mes classes formulaire et action dans des packages séparés; sinon, cela peut devenir trop confus dès l’instant où vous avez plus de deux écrans en place. Ce qui suit est un échantillon de classe ActionForm. C’est le formulaire utilisé pour la page de connexion.

/*
* LoginForm.java
*/
package com.oreilly.forms;

import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionError;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;

/**
* Bean formulaire de la page principale. Il y a deux champs
* utilisés sur ce formulaire pour l'identification.
* <ul>
* <li>username - nom de l'utilisateur
* <li>password - mot de passe
* </ul>
*/
public final class LoginForm extends ActionForm {
private String userName = null;
private String password = null;

/**
* Obtenir le nom de l'utilisateur
*@return String
*/
public String getUserName() {
return (userName);
}
/**
* Modifier le nom de l'utilisateur
* @param userName
*/
public void setUserName(String newUserName) {
userName = newUserName;
}
/**
* Obtenir le mot de passe
*@return String
*/
public String getPassword() {
return (password);
}
/**
* Modifier le mot de passe
* @param password
*/
public void setPassword(String newPassword) {
password = newPassword;
}

/**
* Réinitialiser toutes les propriétés à leur valeur par défaut.
*
* @param mapping Le mapping utilisé pour sélectionner cette instance
* @param request La requête que nous traitons
*/
public void reset(ActionMapping mapping, HttpServletRequest request) {
userName = null;
password = null;

}
/**
* Valide les propriétés qui ont été réglées dans cette requête HTTP
* et retourne un objet <code>ActionErrors</code> qui contient toutes les
* erreurs de validation qui ont été détectées.
* Si aucune erreur n'a été trouvée, retourne <code>null</code> ou un objet
* <code>ActionErrors</code> sans messages d'erreur.
*
* @param mapping Le mapping utilisé pour sélectionner cette instance
* @param request La requête que nous traitons
*/
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
ActionErrors errors = new ActionErrors();
// Pour ce formulaire, seul un nom d'utilisateur est requis
if( userName == null || userName.length()==0 ){
errors.add("userName",new ActionError("error.userName.required"));
}
return (errors);
}
}

Il y a quelques points intéressants à soulever ici. La méthode reset est appelée s’il y a un bouton reset sur le formulaire. Il réinitialise toutes les variables à leur valeur par défaut. La méthode validate() est utilisée pour toute validation spécifique au formulaire. Dans ce cas, nous nous intéressons seulement au fait que l’utilisateur ait fourni son nom. Il peut être possible qu’il n’y ait aucun mot de passe, nous laisserons donc la logique de l’application gérer cela. Sans nom d’utilisateur, l’utilisateur ne peut être authentifié, nous devons donc transmettre une erreur.

Les erreurs peuvent être gérées par ActionErrors dans Struts. Typiquement, tout ce qui se termine par un “s” est une collection d’objets. Donc, ActionErrors est une collection d’ActionError. Vous pouvez traiter un formulaire complet et renvoyer plusieurs erreurs à l’affichage. C’est utile pour les formulaires qui possèdent beaucoup de champs obligatoires et cela évite à l’utilisateur de soumettre sa saisie cinq fois de suite pour cinq erreurs différentes.

Notez aussi que les erreurs montrées dans cet extrait utilisent le fichier ApplicationResource.properties. Le fichier properties est défini dans le fichier web.xml utilisé par l’application toute entière quand Tomcat démarre. Habituellement, il y a un fichier web.xml dans le répertoire WEB-INF de toute application. Pour plus d’informations sur la manière dont est organisée la structure d’une application prête au déploiement, jetez un oeil au guide utilisateur disponible dans le Téléchargement de Tomcat.

Le fichier ApplicationResource permet de définir toutes les chaînes de caractères affichées dans une application. Une recherche est effectuée avec une clé. Dans cet extrait, la clé error.userName.required sera remplacée par le texte de ce message d’erreur : “Un nom d’utilisateur est requis”. Cela est particulièrement commode pour apporter le support multi-linguistique à votre application. Seul l’ ApplicationResource nécessite d’être traduit, et vous pouvez avoir une version espagnole, allemande ou française de votre application.

Cela peut être effectué pour tout ce qui est affiché à l’écran. Le fichier ApplicationResource associé à ce projet ressemble à ceci :

login.title=Login Struts Sample
error.userName.required=Un nom d'utilisateur est requis
error.login.authenticate=Nom d'utilisateur/mot de passe incorrect
errors.footer=</ul><hr>
errors.header=<h3><font color="red">Page
Validation</font></h3>Merci de corriger les
erreurs suivantes avant de continuer :<ul>
applicationResources=Impossible de charger les ressources de l'application{0}

Le titre des pages, les boutons, et tout ce qui nécessite du texte peut être géré dans ce fichier. Nous aborderons l’utilisation des balises Struts pour accéder à ce fichier à partir d’un JSP quand nous arriverons à cette étape dans l’article final de cette série.

Textes originaux en anglais sur O’Reilly - ONJava.com : JSP and Servlets technologies par Sue Spielman

Thierry Le langage JSP et les Servlets Java , , , ,

  1. Pas encore de commentaire
  1. Pas encore de trackbacks
Vous devez être identifié pour poster un commentaire