Aller au contenu

[Struts2] Gestion des jokers dans struts.xml


Messages recommandés

Salut tout le monde,

J'ai un petit problème pas forcément trop gênant dans l'immédiat mais qui résolu m'aiderait pas mal à avoir des applications bien propres pour le boulot. Je cherche à configurer Struts de sorte que l'on puisse tomber sur une belle page d'erreur si on fait n'importe quoi (ou qu'un lien est foireux). Pour cela, j'ai défini une action spécifique que j'ai défini en tant qu'action par défaut. Tout irait bien dans le meilleur des mondes si une autre partie du mapping ne posait pas problème.

En effet, j'utilise aussi des jokers pour limiter le plus possible la taille de mon fichier tout en ayant pas mal de flexibilité au niveau des utilisations possibles pour les différents objets que mon application gère. C'est pas forcément très clair comme ça, mais en voyant mon fichier struts.xml d'exemple vous allez vite comprendre :

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

<struts>
   <package name="default" extends="struts-default" namespace="/">
       <!-- Default page with struts, unknown document -->
       <default-action-ref name="PageNotFound"/>

       <!-- Global error case -->
       <global-results>
           <result name="exception">/exception.jsp</result>
       </global-results>
       <global-exception-mappings>
           <exception-mapping exception="java.lang.Exception" result="exception"/>
       </global-exception-mappings>

       <!-- Unknown document -->
       <action name="PageNotFound">
           <result>/404.jsp</result>
       </action>

       <!-- Mapping for message listing + create from -->
       <action name="Messages" class="test.action.MessagesAction">
           <result name="success">Messages.jsp</result>
           <result name="error">Messages.jsp</result>
           <result name="input">Messages.jsp</result>
       </action>

       <!-- Mapping for the actions on the messages -->
       <action name="*_*" class="test.action.{1}Action" method="{2}">
           <result name="success">{1}.jsp</result>
           <result name="error">{1}.jsp</result>
           <result name="input">{1}.jsp</result>
       </action>
   </package>
</struts>

Voilà le comportement de l'application sachant qu'une méthode 'read' existe dans MessagesAction, mais que ce n'est pas le cas de la méthode 'rand' :

URL					 Comportement attendu	Comportement observé
/Messages.action		Page 'messages'		 Page 'messages'	 - OK
/Messages_read.action   Page 'show message'	 Page 'show message' - OK
/Messages_rand.action   Page 'exception'		Page 'exception'	- OK
/Random.action		  Page '404'			  Erreur serveur	  - KO

Le message par l'erreur serveur est le suivant :

Unable to instantiate Action, test.action.RandomAction,  defined for 'Random' in namespace '/' test.action.RandomAction - action - file:/C:/NetBeansProjects/StrutsTest/build/web/WEB-INF/classes/struts.xml:32:71

L'erreur serveur est due au fait que Struts semble considérer que "Random" ~= "*_*". Or je ne pense pas que cela soit dû au fait que '_' soit un caractère spécial, étant donné que le remplacer par '/' (en ayant bien sûr autorisé ce caractère dans les actions) entraîne le même problème. Et puis on voit bien dans le message d'erreur que {1} = "Random". ({2} semble contenir la chaîne vide, vu que mettre l'attribut class du mapping problématique à "test.action.{1}Action" donne exactement le même message d'erreur que dans le premier cas.)

Bref, utiliserais-je mal les jokers ? Peut-être y a-t-il une autre manière de faire (tout en gardant un struts.xml aussi réduit que possible ; j'en ai un de plus de 300 lignes dans une application que je dois refactorer, améliorer et maintenir car ne prenant en compte aucun cas d'erreur au niveau de Struts, ne faisant pas de validation, etc.) ?

Merci d'avance. :transpi:

Lien vers le commentaire
Partager sur d’autres sites

Bon, j'ai fait d'autres tests et je crois que je commence à voir pourquoi ça fonctionne de la sorte. Les gars qui ont conçu la façon d'utiliser struts.xml ont dû se dire "autant limiter au maximum la taille du fichier, et faire en sorte qu'en cas de jokers multiples on crée implicitement les règles correspondantes aux sous-patterns contenant moins de joker". Ce qui voudrait dire qu'en écrivant ma règle avec deux jokers, j'ai aussi implicitement créé celle-ci :

<action name="*" class="test.action.{1}Action">
<result name="success">{1}.jsp</result>
<result name="error">{1}.jsp</result>
<result name="input">{1}.jsp</result>
</action>

Cela rend au passage ma règle "Message" inutile car incluse dans l'autre règle. Et effectivement, l'application marche de la même manière si je l'enlève. Reste à savoir si ça n'est pas un comportement configurable (pour désactiver ça, je n'aime pas quand il y a des choses implicites pas forcément logiques). Ou alors si j'ai bien compris le comportement lié aux exception-mappings, il va falloir que je modifie la pile des interceptors histoire de récupérer les exceptions ClassNotFound lancées par le mapper plutôt que de les voir affichées directement... J'aurais préféré ne pas avoir à toucher à ça mais bon...

Edit: En fait non, le coup du changement de la position des interceptors ne changera rien, pour la simple raison que 'exception' est le premier interceptor de la pile, donc déjà au plus haut. Mais pourquoi n'attrape-t-il pas la ServletException (ou ClassNotFoundException, si elle est transformée en ServletException qu'après être passée au travers de la pile des interceptors) ?

Lien vers le commentaire
Partager sur d’autres sites

  • 2 semaines après...

Bon bah finalement j'ai plus ou moins laissé tombé, et je vais me contenter d'un fichier struts.xml plus gros que ce sur quoi je partais de base, mais bien moins gros que ce qui existait auparavant. Ci-après le modèle que j'utilise finalement pour les différents éléments contenus dans mon fichier.

<action name="messages" class="test.action.MessagesAction">
<result>messages.jsp</result>
</action>
<action name="messages/*" class="test.action.MessagesAction" method="{1}">
<result>messages.jsp</result>
</action>

Le résultat n'est pas parfait, mais il n'y a rien de trop gênant tant que les utilisateurs ne s'amusent pas à taper des adresses fantaisistes (et encore, trop fantaisiste et ils tombent sur la page 404 que j'ai configuré pour être utilisée avec <default-action-ref>).

Lien vers le commentaire
Partager sur d’autres sites

Archivé

Ce sujet est désormais archivé et ne peut plus recevoir de nouvelles réponses.

×
×
  • Créer...