RSS Feed

Articles associés au tag ‘struts’

Les bonnes pratiques avec Struts 2 – afficher un double select horizontalement

4 June 2008 par SeB 2 commentaires »

Voici le second billet dans la série sur Les bonnes pratiques avec Struts 2.

Introduction

Struts 2 permet de gérer facilement des doubles listes déroulantes (tag <select> en HTML) avec le tag <s:doubleselect>. Le problème est que les listes déroulantes générées avec ce tag s’affichent toujours l’une au dessous de l’autre (ie. verticalement). Or, souvent il est souhaitable que ces listes soient affichées l’une à côté de l’autre (ie. horizontalement).

Solutions

En lisant le code du template par défaut de Struts 2, on se rend compte que le retour à la ligne entre les deux listes est forcé avec le tag <br />. Donc, il n’existe qu’une seule solution : réécrire le template pour le tag <s:doubleselect>. Enfin, il faut juste supprimer le tag <br /> présent dans le fichier doubleselect.ftl (ligne 32 dans la version 2.0.11 de Struts 2). ;-)

Conclusion

Encore une fois, on peut s’étonner de l’ajout par Struts 2 d’un <br /> entre les deux listes déroulantes. De plus, j’ai essayé d’ajouter un nouvel attribut au tag<s:doubleselect> pour paramétrer l’alignement (horizontal et vertical), mais je n’ai pas réussi. :-(

 

Les bonnes pratiques avec Struts 2 – construire des URLs avec les bons paramètres

20 March 2008 par SeB 3 commentaires »

Voici un premier billet dans la série sur Les bonnes pratiques avec Struts 2.

Introduction

Struts 2 permet de construire simplement des URLs avec le tag <s:url>. Le problème est que ce tag ajoute dans l’URL tous les paramètres passés dans l’URL de la page courante.

Solutions

Ce genre de comportement est rarement souhaité et ne concerne de quelques cas bien précis. Pour empêcher l’ajout des paramètres courants, il faut positionner l’attribut includeParams avec la valeur none de cette façon :

<s:url value="myurl" includeParams="none">
 <s:param name="myparam" value="myvalue" />
</s:url>

Cette méthode fonctionne bien. Cependant, dans la pratique, il devient vite pénible de devoir positionner cet attribut à chaque fois que l’on souhaite générer une URL. C’est pourquoi, il est préférable de modifier le fichier de configuration de Struts et d’ajouter dans le fichier struts.xml la ligne suivante :

<constant name="struts.url.includeParams" value="none" />

Conclusion

On peut s’étonner du choix de la valeur par défaut de l’attribut includeParams (qui peut prendre les valeurs none, get ou all). Néanmoins, vous voilà  armé pour construire des URLs propres et sans aucun paramètre parasite.

 

Les bonnes pratiques avec Struts 2

19 March 2008 par SeB Pas de commentaire »

Il y a quelques temps, j’ai commencé une série d’article sur Les bonnes pratiques avec Struts.

Or, mon dernier article sur un comparatif entre Struts 1 et Struts 2 laissait supposer un passage de Struts 1 à Struts 2. Donc, comme un changement en amène un autre, la série sur Les bonnes pratiques avec Struts devient Les bonnes pratiques avec Struts 2.

Les objectifs de cette série reste les mêmes :

  • réaliser un aide mémoire sur l’utilisation de Struts 2
  • partager et confronter les expériences de chacun sur ce framework MVC

Liste des billets :

En attendant strutsez-vous bien. ;-)

 

Struts 1 ou Struts 2

15 November 2007 par SeB 3 commentaires »

Suite à l’arrivée de JSF, le projet Struts a dû se recadrer afin de ne pas de se disperser et de toujours proposer une offre cohérente et surtout compétitive. C’est alors que le projet a été découpé en trois :

  • Struts 1 : la version classique qui existe depuis de nombreuses années.
  • Struts 2 : la nouvelle version résultant de la fusion entre les projets Struts et Webwork.
  • Shale : la version JSF (si je puis dire).

Autant, il est facile de voir la différence entre la version “classique” de Struts et Shale. Autant, une distinction entre Struts 1 et Struts 2 n’est pas évidente pour tout le monde. C’est pourquoi Christophe Bonche de chez Clever Age dresse un portrait de ces deux versions. Dans sa présentation, il explique notamment le cycle de vie standard de ces deux frameworks. Mais l’objectif du document est d’aider le lecteur à choisir entre Struts 1 et Struts 2. Je vous laisse découvrir le résultat de l’analyse sans surprise. ;-)

 

Struts 1.3 – la première version public avec Struts 1.3.5

20 September 2006 par SeB Pas de commentaire »

Jusqu’à présent la version version de Struts était la 1.2.9. La nouvelle version est la 1.3.5. Cette version correspond à la branche de développement de Struts 1.3[1].

Il existe d’importantes différences entre Struts 1.2 et Struts 1.3 :

  • Le projet est découpé en plusieurs JARs séparés correspondant à chaque sous-projet :
    • Core
    • Applications
    • EL
    • Extras
    • Faces
    • Scripting
    • Taglib
    • Tiles
  • Le projet est géré avec Maven 2.
  • Le RequestProcessor reprend le modèle de conception CoR et est configurable via un fichier XML avec Commons Chain.
  • Migration vers J2SE 1.4, Servlet 1.3 et JSP 1.2.
  • Intégration de Commons Validator 1.3.0.
  • Gestion des boutons annuler.
  • Support de l’héritage dans les fichiers de configurations.
  • Détermination des URLs de soumission des formulaires avec les postback actions.
  • Diverses améliorations sur la configuration.

L’annonce de la précédente version beta de Struts 1.3.5 donne plus de détails sur les nouveautés depuis Struts 1.2. L’annonce de la version officielle de Struts 1.3.5 présente également une grande partie des nouveautés.

Il ne vous reste plus qu’à migrer de Struts 1.2 vers 1.3 !

Et pour ceux qui souhaitent en savoir un peu plus sur Struts pour l’année 2006, allez lire de ce pas Struts 2006: An Embarrassment of Riches si vous ne l’avez pas encore fait.

Notes

[1] Annoncé en décembre 2005.

 

Les bonnes pratiques avec Struts – copier les données des formulaires vers les objets métiers

12 September 2006 par SeB Pas de commentaire »

Le quatrième billet dans la série sur Les bonnes pratiques avec Struts.

Introduction

Struts se révèle très pratique pour gérer les formulaires. En effet, il s’occupe de charger les données du formulaire pour l’afficher. Et il récupère les données dans la requête lorsqu’un formulaire est validé.

Côté code Java, cela se traduit par la manipulation de Java beans héritant de la classe ActionForm. Lors de l’appel à la couche métier, il est alors souvent nécessaire de transférer les données un formulaire vers un objet métier (le processus inverse est valable). Cette étape consiste à créer un objet métier, puis à faire appel successif aux getters du formulaire et aux setters de l’objet métier.

Pour être honnête, l’écriture de code n’est pas passionnant, prend de la place et doit être maintenu sérieusement lorsque des champs sont ajoutés ou supprimés.

Solutions

Heureusement pour les utilisateurs de Struts, il existe des outils pour automatiser cette procédure de transfert de données des objets de la vue vers les objets du domaine ou du métier.

BeanUtils

BeanUtils est une bibliothèque fournie par le projet Jakarta qui permet de manipuler simplement des Java beans. Struts l’utilise entre autre pour peupler les formulaires.

Avec BeanUtils, il est possible de copier les données d’un objet source vers un objet destination même s’ils n’ont pas la même classe. Par contre, seuls les attributs ayant les mêmes noms sont copiés.

Exemple de code :

SourceClass srcObject = new SourceClass();
//chargement les données de src
Object DestinationClass dstObject = new DestinationClass();
BeanUtils.copyProperties(dstObject, srcObject);

Dozer

Dozer est qualifié de framework de mapping objet-objet. Concrêtement, il permet de faire du mapping entre des objets de classes différentes. Donc, par exemple entre un objet de formulaire et un objet métier.

Là où Dozer devient intéressant, c’est que ce mapping est configurable et surtout supporte les objets imbriqués (objets en tant qu’attributs). Ainsi, les deux objets utilisés pour une copie ne sont pas obligé d’avoir des attributs avec les mêmes noms. Ils ne sont pas obligés non plus d’avoir la même structure.

Exemple de code :

SourceClass srcObject = new SourceClass();
//chargement les données de src
Object MapperIF mapper = new DozerBeanMapper();
DestinationClass dstObject = (DestinationClass) mapper.map(srcObject, DestinationClass.class);

Exemple de mapping pour faire correspondre les champs login et pwd avec les champs userName et password :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mappings PUBLIC "-//DOZER//DTD MAPPINGS//EN"    "http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd">
<mappings>
	<mapping>
 		<class-a>com.company.project.SourceClass</class-a>
  		<class-b>com.company.project.DestinationClass</class-b>
	  	<field>
 			<a>login</a>
 			<b>userName</b>
	 	</field>
	 	<field>
 			<a>pwd</a>
 			<b>password</b>
	 	</field>
	</mapping>
</mappings>

Exemple de mapping pour faire correspondre les champs commençant par address avec les champs respectifs de l’attribut address :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mappings PUBLIC "-//DOZER//DTD MAPPINGS//EN"    "http://dozer.sourceforge.net/dtd/dozerbeanmapping.dtd">
<mappings>
	<mapping>
		<class-a>com.company.project.SourceClass</class-a>
		<class-b>com.company.project.DestinationClass</class-b>
		<field>
			<a>addressStreet</a>
			<b>address.street</b>
		</field>
		<field>
			<a>addressCity</a>
			<b>address.city</b>
		</field>
	</mapping>
</mappings>

Conclusion

Dans la plupart des cas, BeanUtils est amplement suffisant. De plus, il est directement intégré dans Struts et ne nécessite pas l’installation de bibliothèque externe pour un projet.

Cependant, il arrive que l’objet représentant un formulaire ne soit pas proche dans sa structure à l’objet métier ou aux objets métiers utilisés. Dans ce cas, Dozer se révèle être un puissant outil !

Ces outils permettent également de formater (convertir) les données brutes du formulaire pour les objets métiers.

 

Les bonnes pratiques avec Struts – afficher les formulaires en UTF-8

31 August 2006 par SeB 15 commentaires »

Voici un troisième billet dans la série sur Les bonnes pratiques avec Struts.

Introduction

A partir du moment où une application doit être internationalisée, il est intéressant d’utiliser l’encodage UTF-8 par défaut. Dès lors, un problème d’affichage des valeurs des formulaires se pose avec certains caractères[1].

Solutions

Il existe deux solutions courantes pour répondre à ce problème, qui s’implémentent :

  • dans les méthodes reset() et validate() de la classe ActionForm
  • avec des filtres des servlets

ActionForm.reset & ActionForm.validate

Il suffit simplement d’implémenter ces deux méthodes dans tous vos ActionForm :

public void reset(ActionMapping mapping, HttpServletRequest request) {
 	try {
 		request.setCharacterEncoding("UTF-8");
 	} catch (UnsupportedEncodingException e) {
 		e.printStackTrace();
 	}
 	super.reset(mapping, request);
 }
 public void validate(ActionMapping mapping, HttpServletRequest request) {
 	try {
 		request.setCharacterEncoding("UTF-8");
 	} catch (UnsupportedEncodingException e) {
 		e.printStackTrace();
 	}
 	super.validate(mapping, request);
 }

Cette méthode fonctionne bien. Mais elle pose deux problèmes :

  • Il faut implémenter ces méthodes dans tous les ActionForm. Ce problème peut être contourné par l’implémentation d’une classe de base BaseActionForm.
  • Le comportement des DynaActionForm n’est pas impacté par cette astuce.

Filtres de servlet

Il faut écrire un filtre de servlet qui va modifier l’encodage de toutes les requêtes :

import java.io.IOException;
 import javax.servlet.FilterChain;
 import javax.servlet.FilterConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 public class EncodingFilter implements javax.servlet.Filter {
 	private String encoding;
 	public void init(FilterConfig filterConfig) throws ServletException {
 		this.encoding = filterConfig.getInitParameter("encoding");
 	}
 	public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
 		request.setCharacterEncoding(encoding);
 		filterChain.doFilter(request, response);
 	}
 	public void destroy() {
 	}
 }

Ensuite, il faut déclarer le filtre dans le fichier /WEB-INF/web.xml ainsi (avant tous les autres filtres) :

<filter>
 	<filter-name>Encoding Filter</filter-name>
 	<filter-class>EncodingFilter</filter-class>
 	<init-param>
 		<param-name>encoding</param-name>
 		<param-value>UTF-8</param-value>
 	</init-param>
 </filter>
 <filter-mapping>
 	<filter-name>Encoding Filter</filter-name>
 	<url-pattern>/*</url-pattern>
 </filter-mapping>

Maintenant toutes les requêtes sont correctement lues avec l’encodage UTF-8.

Conclusion

La seconde solution est non-intrusive et plus sûre. De plus, elle n’est pas spécifique à Struts et peut être utilisée pour n’importe quel type d’application web J2EE.

Il ne reste plus qu’à traduire vos applications en chinois. :-D

Notes

[1] Comme les caractères accentués tels que é, è, à, ô, …

 

Les bonnes pratiques avec Struts – valider les formulaires

26 August 2006 par SeB 2 commentaires »

Voici un second billet dans la série sur Les bonnes pratiques avec Struts.

Introduction

Une fois un formulaire saisi par un utilisateur, il faut qu’il soit validé un minimum. Cette validation peut se faire à deux endroits :

  • côté client : dans le butineur avec du code Javascript
  • côté serveur : dans le serveur d’application avec du code Java

La validation côté client permet d’éviter un aller-retour avec le serveur dans le cas où un champ du formulaire est invalide. Par contre, il est impossible de s’assurer que le contrôle côté client a réellement été effectué[1]. C’est pourquoi, il faut toujours réaliser les contrôles côté serveur.

Tout le monde s’accorde pour dire qu’il est souhaitable d’effectuer des contrôles côté client[2] et côté serveur[3].

Solutions

Struts propose plusieurs façon pour gérer ces contrôles :

ActionForm.validate

Le formulaire à coder doit hériter de la classe ActionForm et ré-implémenter la méthode ActionErrors validate(ActionMapping mapping,HttpServletRequest request).

Cette méthode est appelée à chaque fois qu’un objet ActionForm est chargé. Cela permet d’automatiser la validation du formulaire côté serveur. Voici un exemple d’implémentation :

public class LoginForm extends ActionForm {
	private String login;
	private String password;
	public void setLogin(String login) {
		this.login = login;
	}
	public string getLogin() {
		return login;
	}
	public void setPassword(String password) {
		this.password = password;
	}
	public string getPassword() {
		return password;
	}
	public ActionErrors validate(ActionMapping mapping,HttpServletRequest request) {
		ActionErrors errors = new ActionErrors();
		if ( login==null || login.lenght<=8) {
			errors.add("error",new ActionMessage ("error.login"));
		}
		if ( password==null || password.lenght<=8) {
			errors.add("error",new ActionMessage ("error.password"));
		}
		return errors;
	}
}

Struts Validator

Struts Validator est un framework à part entière qui permet d’effectuer la validation de formulaire côté client et côté serveur par simple configuration. En effet, il faut configurer les règles de validations dans un fichier XML, ensuite Struts Validator génère le code Java et le code Javascript à exécuter lors de la validation du formulaire.

Pour cela , il faut ajouter la déclaration suivante dans le fichier /WEB-INF/validation.xml :

<formset language="">
	<form name="loginForm">
		<field property="login" depends="required,minlength">
			<arg0 key="welcome.login.login"/>
			<arg1 name="minlength" key="${var:minlength}" resource="false" />
			<var>
				<var-name>minlength</var-name>
				<var-value>8</var-value>
			</var>
		</field>
		<field property="password" depends="required,minlength">
			<arg0 key="welcome.login.password"/>
			<arg1 name="minlength" key="${var:minlength}" resource="false" />
			<var>
				<var-name>minlength</var-name>
				<var-value>8</var-value>
			</var>
		</field>
	</form>
</formset>

De plus, le formulaire doit être déclaré de la façon suivante dans la page JSP :

<html:javascript formName="loginForm" dynamicJavascript="true" staticJavascript="true" />
<html:form action="/login" focus="login" onsubmit="return validateLoginForm(this);">
	<html:text property="login" size="16" /><br />
	<html:password property="password" size="16" redisplay="false" /><br />
	<html:submit value="login" />
</html:form>

Ainsi, le code Javascript est générer pour contrôler le formulaire côté client. Et Struts contrôle côté serveur le formulaire une nouvelle fois.

Conclusion

Le framework Validator permet de centraliser les règles de contrôle. De plus, grâce à ce système les contrôles Javascript et Java sont toujours à jour.

Je n’y ai pas encore trouvé d’utilité eu le besoin, mais certaines personnes utilisent la combinaison des deux méthodes.

Si toutes les règles de contrôles proposées par Struts Validator ne sont pas suffisantes, il est possible de créer ses propres règles. Comme cela  a déjà été présenté avec la règle compareTo pour Struts Validator. Faire référence au validateur compareTo.

Maintenant, vous n’aurez plus d’excuse pour ne pas réaliser de contrôle sur vos formulaires !

Notes

[1] Le Javascript peut être désactivé dans le butineur. Le client peut être un programme autre qu’un butineur

[2] Pour améliorer l’ergonomie.

[3] Pour améliorer la sécurité.

 

Les bonnes pratiques avec Struts – proteger l’accès des pages JSP

7 July 2006 par SeB Pas de commentaire »

Voici un premier billet dans la série sur Les bonnes pratiques avec Struts.

Introduction

La sécurité des applications web est un point sensible. En effet, il y a toujours un utilisateur qui essaie de casser la sécurité du système. Ce type d’utilisateur cherche dans le code source des pages HTML des informations sur le chemin des pages JSP. Ensuite, il tente de les exécuter manuellement et de modifier les données du contexte.

Solutions

Pour se prémunir de ce genre d’attaque, il faut interdire l’accès aux pages JSP par les utilisateurs. Deux méthodes sont possibles :

  • la configuration de l’application web
  • l’organisation des pages

Configuration de l’application web

Il faut simplement ajouter les lignes suivantes dans le fichier web.xml :

<security-constraint>
   <web-resource-collection>
     <web-resource-name>no_access</web-resource-name>
     <url-pattern>*.jsp</url-pattern>
   </web-resource-collection>
   <auth-constraint/>
 </security-constraint>

Organisation des pages

Le répertoire WEB-INF n’est pas accessible par les utilisateurs d’une application web. Il suffit donc de placer toutes les pages JSP dans ce répertoire[1]. Ensuite les redirections dans Struts doivent pointer vers /WEB-INF/... au lieu de /....

Conclusion

Je préfère la seconde solution[2] qui autorise plus de souplesse. Vous remarquez que les deux méthodes sont très simples et ne demande que très peu d’effort. Pourtant elles améliorent la sécurité[3] de vos applications web. Alors, n’hésitez pas à sécuriser l’accès de vos pages JSP.

Notes

[1] Par exemple, dans WEB-INF/pages ou WEB-INF/jsp.

[2] C’est également la solution que l’on rencontre le plus.

[3] Également la stabilité.

 

Les bonnes pratiques avec Struts

6 July 2006 par SeB 2 commentaires »

J’y pense depuis longtemps. Et c’est décidé. Je me lance dans une série de billets sur Struts !

Cette série s’intitule Les bonnes pratiques avec Struts. Je vais partager avec vous toutes les astuces et les bonnes pratiques que je peux utiliser lorsque je travaille avec Struts.

L’objectif est double :

  • réaliser un aide mémoire sur l’utilisation de Struts
  • partager et confronter les expériences de chacun sur ce framework MVC

Liste des billets :

En attendant strutsez-vous bien. ;-)