Guide De Démarrage Rapide
Introduction
Le but de ce guide est de vous initier et de vous rendre autonome dans Stripes le plus vite possible. Il contient une section sur la configuration d'une application web utilisant Stripes, et une autre sur le développement de votre première application Stripes.
Pré-requis
Stripes utilise différentes caractéristiques de Java 1.5 comme les Annotations et les Génériques. Il s'appuie aussi beaucoup sur les technologies des spécifications Servlet 2.4/JSP 2.0. C'est la raison pour laquelle vous aurez besoin du JDK v1.5 (disponible maintenant pour presque toutes les plateformes principales), et d'un Conteneur de Servlet avec qui adhère à la spécification Servlet 2.4 (par exemple Tomcat 5.x, qui est gratuit, et les plus récentes versions de l'excellent Caucho Resin, gratuit seulement pour des usages non-commerciaux).
Un minimum d'expérience du développement JSP est nécessaire, ainsi que les rudiments du Langage d'Expressions (EL), sans toutefois le maîtriser totalement.
Configuration de Stripes
Stripes est conçu de façon à requérir le minimum de configuration possible. Avant de pouvoir l'utiliser il suffit juste de configurer le Stripes Filter ainsi que le Stripes Dispatcher Servlet dans le fichier web.xml
de votre application web. Une configuration normale ressemblerait à ceci :
<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4"> <filter> <display-name>Stripes Filter</display-name> <filter-name>StripesFilter</filter-name> <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class> <init-param> <param-name>ActionResolver.Packages</param-name> <param-value>net.sourceforge.stripes.examples</param-value> </init-param> </filter> <filter-mapping> <filter-name>StripesFilter</filter-name> <url-pattern>*.jsp</url-pattern> <dispatcher>REQUEST</dispatcher> </filter-mapping> <filter-mapping> <filter-name>StripesFilter</filter-name> <servlet-name>StripesDispatcher</servlet-name> <dispatcher>REQUEST</dispatcher> </filter-mapping> <servlet> <servlet-name>StripesDispatcher</servlet-name> <servlet-class>net.sourceforge.stripes.controller.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <servlet-mapping> <servlet-name>StripesDispatcher</servlet-name> <url-pattern>*.action</url-pattern> </servlet-mapping> </web-app>
Le paramètre ActionResolver.Packages
Stripes découvre automatiquement vos ActionBeans au démarrage en parcourant le classpath de votre application web. Ceci vous évite de lister tous vos ActionBeans dans un fichier quelque par, mais il faut donner des piste à Stripes. Pour cela, utiliser l'init-param ActionResolver.Packages
du Filtre Stripes (StripesFilter) pour indiquer un ou plusieurs répertoires racine. N'utiliser pas .*
à la fin d'un répertoire car des sous-répertoires sont automatiquement inclus. Utiliser des virgules pour séparer plusieurs répertoires racine.
l'init-param ActionResolver.Packages
est le seul paramètre requis par le Filtre Stripes.
Puis il faudra que vous placiez stripes.jar
dans votre classpath (normalement WEB-INF/lib
). Ceci est la seule dépendance au moment de la compilation pour développer avec Stripes. Pour développer et utiliser Stripes vous aurez besoin de copier les fichers libraires ci-dessous fournis avec Stripes dans votre classpath :
commons-logging.jar (1.1)
- Apache Commons Logging est utilisé afin de fournir une interface de logging avec une implémentation agnostique.cos.jar
- le package libraire com.oreilly.servlets, grâce à Jason Hunter, est utilisé pour gérer les uploads de fichiers multi-part à partir de formulaires d'envoi
Les fichiers libraires ci-dessus sont fournis avec la distribution de Stripes, et ont été testés avec Stripes. Des versions plus récentes peuvent fonctionner, mais vous serez en territoire inconnu.
De plus, les messages de journalisation (logging) de Stripes peuvent vous aider. Pour cela, vous aurez besoin de fournir soit votre propre configuration Log4J, soit une autre configuration compatible avec Commons Logging. Le jar Log4J, log4j-1.2.9.jar
, est distribué avec Stripes. Quelques exemples de configurations suivent ci-dessous :
org.apache.commons.logging.Log=org.apache.commons.logging.impl.Log4JLogger
### direct log messages to stdout ### log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.Target=System.out log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### direct messages to file ### log4j.appender.file=org.apache.log4j.FileAppender log4j.appender.file.File=/tmp/stripes.log log4j.appender.file.layout=org.apache.log4j.PatternLayout log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n ### set log levels - for more verbose logging change 'info' to 'debug' ### log4j.rootLogger=INFO, stdout, file log4j.logger.net.sourceforge.stripes=DEBUG
Les fichiers de configuration logging doivent être placés dans votre classpath, ex. /WEB-INF/classes
.
La dernière partie à être plaçée est le fichier StripesResources.properties
; il faudra tout simplement le copier dans /WEB-INF/classes
. StripesResources.properties
est utilisé (par défaut) pour contenir des messages d'erreurs qui sont utilisés pour la validation incluse par défaut dans Stripes et la validation faite dans les ActionBeans, et il doit pouvoir être retrouvé dans le classpath. Voici un fragment exemple du fichier :
# Validation error messages used by Stripes' built in type converters converter.number.invalidNumber=The value ({1}) entered in field {0} must be a valid number converter.byte.outOfRange=The value ({1}) entered in field {0} was out of the range {2} to {3} converter.short.outOfRange=The value ({1}) entered in field {0} was out of the range {2} to {3} converter.integer.outOfRange=The value ({1}) entered in field {0} was out of the range {2} to {3} converter.float.outOfRange=The value ({1}) entered in field {0} was out of the range {2} to {3} converter.enum.notAnEnumeratedValue=The value "{1}" is not a valid value for field {0} converter.date.invalidDate=The value ({1}) entered in field {0} must be a valid date converter.email.invalidEmail=The value ({1}) entered is not a valid email address ...
Mon premier Stripe
Pour la première application nous allons développer une calculatrice simple d'une page qui contient deux chiffres et en fait l'addition, puis peut-être d'autres opérations plus tard. Tout d'abord, concevons la JSP. L'exemple qui suit est le minimum dont nous avons besoin pour notre JSP. Il vous faut le placer dans un dossier qui s'appelle 'quickstart' au-dessous la racine de votre application web.
La JSP
<%@ page contentType="text/html;charset=UTF-8" language="java" %> <%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld"%> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html> <head><title>Mon Premier Stripe</title></head> <body> <h1>Calculatrice Stripes</h1> Bonjour, Je suis le Calculatrice Stripes. Je peux seulement faire une addition. Peut-être un jour un gentil développeur m'apprendra comment faire d'autres choses ? <stripes:form beanclass="net.sourceforge.stripes.examples.quickstart.CalculatorActionBean" focus=""> <table> <tr> <td>Numéro 1 :</td> <td><stripes:text name="numberOne"/></td> </tr> <tr> <td>Numéro 2 :</td> <td><stripes:text name="numberTwo"/></td> </tr> <tr> <td colspan="2"> <stripes:submit name="addition" value="Add"/> </td> </tr> <tr> <td>Resultat :</td> <td>${actionBean.result}</td> </tr> </table> </stripes:form> </body> </html>
La première chose qui nous intéresse sur la page ci-dessus est à la deuxième ligne, celle qui commence avec <%@ taglib ....
qui importe le Stripes Tag Library pour l'utiliser sur la page. Puis, un peu plus bas, la ligne :
<stripes:form beanclass="net.sourceforge.stripes.examples.quickstart.CalculatorActionBean" focus="">
ouvre un tag stripes:form
. Ce tag fait beaucoup de choses dont nous n'allons pas parler ici, et produit finalement un tag form HTML sur la page une fois qu'elle se présente. L'attibut focus=""
indique à Stripes de mettre le focus dans le premier champs visible (ou le premier champ en erreur, si il y en a).
Après ça, nous pouvons voir deux tags, qui ressemblent :
<stripes:text name="numberOne"/>
Ceci est l'équivalant en Stripes du tag HTML <input type="text"/>
, mais qui a une fonction de pre-population et re-population de la data formulaire, et peut modifier la façon dont un tag s'affiche quand il y a des erreurs. Le nom numberOne
est le même que celui de la propriété dans l'ActionBean qui reçoit la requête.
Au lieu d'un <input type="submit"/>
nous voyons :
<stripes:submit name="addition" value="Add"/>
Le tag stripes:submit
a aussi pour fonction de placer le texte localisé sur le bouton, dont on n'a pas besoin ici, donc le tag utilise tout simplement l'attribut de 'value' qui est 'Add'. Le nom du bouton submit, 'addition', est très important car il est lié à la méthode qui sera demandée à l'ActionBean
recevant la requête.
Enfin, une courte expression EL est utilisée pour montrer la propriété result
de l'ActionBean si celle-ci est présente.
<td>${actionBean.result}</td>
Nous sommes maintenant prêt à voir notre page! Quand elle s'affiche pour la première fois il n'existe pas d'ActionBean (le tag stripes:form
ne crée pas d'instance de l'ActionBeans et nous n'avons pas posté ce formulaire).
Page exemple de la calculatrice après n'avoir écrit que la JSP
L'ActionBean
Un ActionBean est l'objet qui reçoit les informations envoyées dans les requêtes et qui traite les données de l'utilisateur. Il définit à la fois les propriétés et que la logique de traitement du formulaire. Si on compare avec Struts, alors, l'ActionBean est l'équivalent de l'ActionForm et de l'Action combinés dans une seule classe.
Il faut noter que Stripes n'a aucun besoin de configuration externe pour connaître les implémentations de l'ActionBean dans une application, ni pour faire une liaison entre le JSP et l'ActionBean. Toute l'information nécessaire est dans l'ActionBean lui-même. Jetons alors un coup d'oeil à l'ActionBean simple qui reçoit la requête de la calculatrice.
package net.sourceforge.stripes.examples.quickstart; import net.sourceforge.stripes.action.DefaultHandler; import net.sourceforge.stripes.action.Resolution; import net.sourceforge.stripes.action.ForwardResolution; import net.sourceforge.stripes.action.ActionBean; import net.sourceforge.stripes.action.ActionBeanContext; /** * Une action de calcul simple. * @author Tim Fennell */ public class CalculatorActionBean implements ActionBean { private ActionBeanContext context; private double numberOne; private double numberTwo; private double result; public ActionBeanContext getContext() { return context; } public void setContext(ActionBeanContext context) { this.context = context; } public double getNumberOne() { return numberOne; } public void setNumberOne(double numberOne) { this.numberOne = numberOne; } public double getNumberTwo() { return numberTwo; } public void setNumberTwo(double numberTwo) { this.numberTwo = numberTwo; } public double getResult() { return result; } public void setResult(double result) { this.result = result; } @DefaultHandler public Resolution addition() { result = getNumberOne() + getNumberTwo(); return new ForwardResolution("/quickstart/index.jsp"); } }
Notez que nous avons utiliser le nom de la classe de l'ActionBean dans le tag stripes:form
. Néanmoins, c'est bon à savoir comment Stripes produit un URL à partir d'un nom de classe. Si vous regardez le code source de la page, vous verrez action="/examples/quickstart/Calculator.action
dans l'HTML. Par défaut Stripes examinera les {{ActionBean}}s et détermine leur URL basé sur leur noms de classe et leur chemin d'accès. Pour convertir les noms de classe et créer les URL, Stripes...
- Enlève les noms de package jusqu'aux noms de paquetages comme 'web', 'www', 'stripes' and 'action'
- Enlève 'Action' et 'Bean' (ou 'ActionBean') si le nom de classe se termine comme cela
- Le convertit pour avoir une URL et ajoute '.action'
Donc dans le cas ci-dessus, net.sourceforge.stripes.examples.quickstart.CalculatorActionBean
est devenu une URL selon la transformation suivante :
- examples.quickstart.CalculatorActionBean
- examples.quickstart.Calculator
- /examples/quickstart/Calculator.action
Notez que l'URL generée à partir du nom de la classe s'accorde avec l'action spécifiée dans le tag stripes:form
dans la JSP. Dans ces deux cas l'action spécifiée est relative à la racine de l'application web. Tout ceci est détaillé dans la JavaDoc pour NameBasedActionResolver (fonctionnement et extension afin de générer des URLs différentes).
Outrepasser les Alliances d'URL
Les URLs generés par Stripes sont seulement le fonctionnement par défaut. Pour outrepasser l'URL qui est liée avec un ActionBean, il suffit d'annonter la classe avec l'annotation @UrlBinding
. Ex. nous aurions pu écrire :
... @UrlBinding("/qs/calc") public class CalculatorActionBean ... ...
ce qui aurait nécessité ceci dans le source de la page HTML :
<stripes:form action="/qs/calc" ... >
Puis, la déclaration de la classe
public class CalculatorActionBean implements ActionBean
ActionBean
(si vous ne l'avez pas déjà compris) est une interface, ce n'est pas une classe de base. Donc vos ActionBeans peuvent étendre n'importe quelle classe. L'interface ActionBean
spécifie deux méthodes (à implémenter dans la classe) :
public ActionBeanContext getContext() { return context; } public void setContext(ActionBeanContext context) { this.context = context; }
Ces fonctions permettent à l'ActionBean
d'accéder à l'ActionBeanContext
. Ce dernier permet d'accéder aux objets HttpServletRequest
et HttpServletResponse
si vous en avez besoin (le moins souvent possible, espérons-le !), ainsi qu'à beaucoup d'autres informations sur la requête (ex. des messages d'erreur).
Alors que les accesseurs 'getXxx' et 'setXxx' pour les trois propriétés (numberOne
, numberTwo
et result
) définis sur l'ActionBean ne sont pas trop intéressantes, vous aurez noté qu'elles sont cependant nécessaires (sauf si les propriétés sont public
, mais ce n'est pas recommandé). Stripes accède aux valeurs des ActionBeans par le mécanisme normal pour des JavaBeans en utilisant les accesseurs getXxx et setXxx, et si elles n'existent pas vous obtiendrez des erreurs. Les trois propriétés (donc trois paires de getXxx/setXxx) dans l'ActionBean s'accordent aux noms utilisés dans la JSP.
Venons-en au plus intéressant :
@DefaultHandler public Resolution addition() { result = numberOne + numberTwo; return new ForwardResolution("/quickstart/index.jsp"); }
Vu que cette méthode est declarée public
et retourne une Resolution
, Stripes l'indentifiera comme "gestionnaire d'événement". Quand une requête arrive au CalculatorActionBean
, et que l'utilisateur clique sur un bouton ou une image avec le nom (le nom, ne pas la valeur) "addition" qui s'accorde avec le nom d'une méthode gestionnaire d'évènement, Stripes l'invoquera. De même que pour les URLs d'Action, nous pouvons outrepasser le nom de l'événement qui s'accorde avec une fonction avec l'annotation @HandlesEvent
si nous voulons :
@HandlesEvent("calcul") @DefaultHandler public Resolution addition() { //... }
donc nous devons modifier notre JSP comme ce qui suit :
<stripes:submit name="calcul" value="Add"/>
L'annotation @DefaultHandler
indique à Stripes que si jamais il ne sait pas quel bouton est cliqué (car normalement l'utilisateur tappe 'entrer' sur le clavier au lieu de cliquer sur un bouton), il doit choisir celle-ci.
Vous avez peut-être noté qu'il n'y a aucune fonction générique comme execute()
ou do
dans l'interface ActionBean. Toutes les fonctions qui gérent des événements sont des fonctions normales qui ont une signature reconnaissable (public
, non-abstract
, rendent une Resolution
) ou qui ont été annotées pour informer Stripes. Stripes apelle ces fonctions gestionnaires d'événements, vu qu'elles gèrent des événements à partir du navigateur. Des fonctions gestionnaires d'événements retournent normalement une Resolution
pour que Stripes sache quoi faire après que la méthode ait été invoquée (elles peuvent retourner n'importe quoi, mais si ce n'est pas une Resolution
, Stripes l'ignorera).
Notre méthode additionne les deux chiffres ensemble et range la somme dans la propriété result
puis nous dirige vers la même JSP dont nous venons en retournant une ForwardResolution
. C'est tout!
Maintenant l'ActionBean est écrit, on peut y ajouter deux plus deux
Cette simple JSP, et cet ActionBean
concis sont tout ce dont nous avons besoin pour obtenir un exemple qui fonctionne en Stripes. Mais nous pouvons faire encore mieux pour pas grand chose.
Ajouter de la Validation
Commençons d'abord par ajouter un peu de validation à la page. Il est plus sûr de mentionner qu'un utilisateur devrait toujours entrer les deux chiffres pour faire une addition. Pour faire cela nous annotons tout simplement les propriétés de l'ActionBean
. Cela peut être fait soit sur les propriétés elles-mêmes, sur les fonctions getXxx, ou sur les fonctions setXxx. Alors qu'il est possible de mélanger les différentes façons d'annoter l'ActionBean, nous suggérons que vous choisissiez un élément type (propriétés, getXxx ou setXxx) et annotiez toujours de la même façon votre ActionBean
. De plus, n'oubliez pas d'importer la classe Validate
.
@Validate(required=true) private double numberOne; @Validate(required=true) private double numberTwo;
Maintenant si un utilisateur oublie d'entrer soit une soit les deux valeurs, il obtiendra une ou plusieurs erreurs de validation. Pour afficher une erreur quelle qu'elle soit à l'utilisateur, nous devons ajouter un tag stripes:errors à la JSP, par exemple comme ce qui suit :
<stripes:form action="/quickstart/Calculator.action"> <stripes:errors/>
Le tag <stripes:errors/>
affichera toutes les erreurs de validation pour le formulaire s'il y en a. Sa présentation est configurable, mais nous ne parlerons pas de ça ici. De plus tout champ sur le formulaire qui cause une erreur aura son attribut de classe css changé à error
pour indiquer une erreur. Donc si nous ajoutions ce qui suit à la section <head></head>
du JSP, les champs erronés auraient un fond jaune.
<style type="text/css"> input.error { background-color: yellow; } </style>
Comment Stripes sait-il que la valeur envoyée est un chiffre et pas un mot ? En fait Stripes à une longueur d'avance sur nous. Il sait que les propriétés numberOne
et numberTwo
sont de type double
et il a déjà appliqué des validations qui ne sont applicables qu'aux doubles. Allez-y, essayez de rentrer des lettres ! Cela ressemblera à ça :
Validation en Action(Beans)!
Ajouter (ou plutôt diviser) une autre Opération
C'est déjà pas mal, mais pourquoi ne pas construire d'autres opérations ? Disons des divisions ? Et bien, c'est extrêmement facile avec Stripes. D'abord nous faisons un ajout rapide à la JSP :
<td colspan="2"> <stripes:submit name="addition" value="Add"/> <stripes:submit name="division" value="Divide"/> </td>
Puis nous ajoutons une nouvelle méthode (gestionnaire d'évènement) à l'ActionBean :
public Resolution division() { result = numberOne / numberTwo; return new ForwardResolution("/quickstart/index.jsp"); }
Les validations que nous avons définies auparavant s'appliquent lorsque l'événement "division" est invoqué, comme lorsque l'événement "addition" est invoqué. Cependant, il vaut mieux que nous nous assurions que lorsqu'un événement division
est invoqué, l'utilisateur n'essaie pas de piéger le système en divisant par zéro. Nous pourrions écrire le code de validation dans la méthode division()
si nous voulions, mais à la place, voyons comment ajouter une méthode seulement spécifique à la validation (avec l'annotation @ValidationMethod
) :
@ValidationMethod(on="division") public void eviterDeDiviserParZero(ValidationErrors errors) { if (this.numberTwo == 0) { errors.add("numberTwo", new SimpleError("La division par zéro est interdite.")); } }
Les fonctions qui sont spécifiques à la validation sont marquées d'une annotation @ValidationMethod
pour indiquer à Stripes de les executer en priorité, avant les méthodes de gestion d'évènements. Sauf si spécifié autrement, Stripes exécutera la méthode de validation pour tous les évènements; dans ce cas-ci, nous l'avons réduite afin fonctionner seulement pour les évènements division
. La méthode reçoit une référence à l'objet ValidationErrors
qui est utilisée pour stocker les erreurs de validation pour l'évènement courant.
La méthode vérifie si le dénominateur est zéro et si c'est le cas, elle crée une instance de l'objet SimpleError
pour stocker un message d'erreur. Cette méthode marche, mais elle est assez rapide et pas très propre. Il serait meilleur de créer une instance de l'objet de LocalizableError et de lui fournir avec le clé d'un message stocké dans le fichier StripesResources.properties
Ressources
- Le code source pour cette application exemple est inclus quand vous téléchargez Stripes ici. Un WAR prêt à l'utilisation qui comporte cette application exemple est aussi inclus, ainsi que...
- L'Application Exemple « Bugzooky » est une application exemple plus détaillée qui démontre quelques-unes des caractéristiques les plus avancées de Stripes
- La section Documentation de Stripes inclut de la documentation de référence ainsi que des conseils et méthodes : "How To's"