IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JSF Java Discussion :

RichFaces - Utilisation de l'attribut action


Sujet :

JSF Java

  1. #1
    Membre confirmé Avatar de Lordsephiroth
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 199
    Points : 494
    Points
    494
    Par défaut RichFaces - Utilisation de l'attribut action
    Bonjour à tous,

    Je suis tout nouvellement arrivé dans JSF et RichFaces, et je me retrouve confronté à un problème que je n'arrive pas à comprendre.

    J'ai défini un élément de menu comme suit (menuContentLink.xhtml) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
        <rich:panelMenuItem hoverClass="panelMenuItemHover" label="#{label}" action="#{action}" icon="/resources/images/icons/empty.gif" style="background-color: #F4F4F4;">
          <a4j:actionparam name="include" value="#{include}" assignTo="#{NavigationBean.contentInclude}" />
        </rich:panelMenuItem>
    Et je réalise l'appel à ce composant par ce code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    <mytags:menuContentLink label="#{msgs.newAgenda}" action="#{AgendaBean.clear}" include="/pages/includes/leftNavigationAgenda/agendaEdit.xhtml" />
    Le paramètre include fonctionne parfaitement et NavigationBean est correctement mis à jour avec l'adresse de la prochaine page à mettre dans le panel principal de ma page. Par contre, le clic sur le lien qui s'affiche exécute l'action et lève cette exception :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    javax.faces.el.EvaluationException: javax.el.PropertyNotFoundException: /WEB-INF/myTags/menuContentLink.xhtml @7,169 action="#{action}": /pages/includes/navigation/leftNavigationAgenda.xhtml @9,150 action="#{AgendaBean.clear}": Property 'clear' not found on type ch.test.presentation.web.beans.AgendaBean
    Mon bean est pourtant tout simple et voici le code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    package ch.test.presentation.web.beans;
     
    import java.io.Serializable;
     
    import org.apache.log4j.Logger;
     
    import ch.test.common.dto.AgendaDTO;
    import ch.test.presentation.web.util.ServiceLocator;
     
    public class AgendaBean implements Serializable {
     
      private static final long serialVersionUID = 1L;
      private AgendaDTO agenda = new AgendaDTO();
      private static final Logger logger = Logger.getLogger(AgendaBean.class);
     
      public void save(){
    	  if(agenda.getAgendaId() == null){
    		  ServiceLocator.getApplicationService().insertAgenda(this.agenda);
    	  }
    	  else{
    		  ServiceLocator.getApplicationService().updateAgenda(this.agenda);
    	  }
      }
     
      public void search(){
    	  if(agenda.getAgendaId() != null){
    		  this.agenda = ServiceLocator.getApplicationService().findAgenda(agenda.getAgendaId());
    	  }
      }
     
      public void clear(){
    	  logger.debug("Clearing the AgendaBean state");
    	  this.agenda = new AgendaDTO();
      }
     
      public AgendaDTO getAgenda(){
    	  return this.agenda;
      }
     
      public void setAgenda(AgendaDTO agenda){
    	  this.agenda = agenda;
      }
     
    }
    La fonction clear est donc bien définie dans le bon bean, je ne vois pas pourquoi il n'est pas possible de l'appeler de la façon dont je l'ai faite (en passant l'action à réaliser en paramètre au travers de l'attribut "action" de mon composant menuContentLink).

    J'arrive par contre parfaitement à appeler save() et search() à d'auters endroit de l'application, typiquement avec l'appel ci-dessous :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    <a4j:commandButton value="insert" action="#{AgendaBean.save}" reRender="content">
    		<a4j:actionparam name="include" value="/pages/includes/leftNavigationAgenda/agendaPrint.xhtml" assignTo="#{NavigationBean.contentInclude}" />
    	</a4j:commandButton>
    Auriez-vous une idée pourquoi l'appel par l'intermédiaire d'un passage par attribut ne fonctionne pas dans mon cas ?

    Merci de m'indiquer si il faut plus de précisions par rapport à mon code, je donnerai plus de détails si besoin.
    Always code as if the guy maintaining your application is a violent psychopath!
    Site personnel sur la saga Final Fantasy : http://www.final-fantasy.ch

  2. #2
    Rédacteur
    Avatar de romaintaz
    Homme Profil pro
    Java craftsman
    Inscrit en
    Juillet 2005
    Messages
    3 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Java craftsman
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2005
    Messages : 3 790
    Points : 7 275
    Points
    7 275
    Par défaut
    Malheureusement, ce n'est pas si simple...

    Si je comprends bien ton composant perso (<mytags:menuContentLink>), celui-ci définit des attributs, qui vont être passés à son contenu (une composition), en l'occurrence ton <rich:panelMenuItem .../>.

    Mais quand tu fais ça, la valeur des attributs est évaluée au moment où JSF / Facelets va les donner à la composition.
    Pour le label, ça se passe bien, car JSF va appeler msgs.getNewAgenda() et va filer la valeur évaluée à la composition.
    Dans le cas de action, JSF va chercher la propriété (et non l'action) clear, autrement dit il va faire un AgendaBean.getClear().

    Tu ne peux pas passer simplement une action vers une composition. C'est plus complexe. Ne peux-tu pas faire autrement ? Ne peux tu pas créer un composant Java (et non composition) pour mytags:menuContentLink ?
    Nous sommes tous semblables, alors acceptons nos différences !
    --------------------------------------------------------------
    Liens : Blog | Page DVP | Twitter
    Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
    Critiques : Apache Maven

  3. #3
    Membre confirmé Avatar de Lordsephiroth
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 199
    Points : 494
    Points
    494
    Par défaut
    Bonjour Romain et merci pour la réponse.

    Effectivement, la définition de menuContentLink est bien dans une balise de composition, dans une TagLib que j'ai définie. Ta compréhension de ce que je cherche à faire est tout à fait juste.

    Il y a une petite chose que je ne comprends pas dans ton explication : tu m'indiques que la valeur de l'attribut "action" est évaluée au moment où elle est passée à la composition. Donc si je reformule ce que je comprends de cette remarque, que le "AgendaBean.clear" devrait être exécuté avant d'arriver dans la composition. De plus, comment JSF / Facelet détermine d'appeler un getClear() ou un clear() ? Car avec action="#{AgendaBean.save}" dans le dernier morceau de code que j'avais mis, c'est bien la fonction save() qui est appelée. J'ai du mal à comprendre la différence, les deux sont dans un action="".

    Je comprends par cette remarque, que AgendaBean.clear devrait être exécuté même si je ne mets pas action="#{action}" dans la composition, ce qui n'est pas le cas. Je n'ai plus aucune exception lorsque je supprime de la composition le action="#{action}", par contre rien ne s'exécute lorsque je clique le lien.

    Ce que je cherche à faire est relativement simple : j'ai réalisé trois compositions nommés agendaEdit, agendaGrid et agendaPrint. Comme leur nom l'indique, l'une est une vue en édition, la seconde une vue d'affichage multi-élément dans un dataTable, la dernière une vue en affichage détaillée d'un élément particulier. Des vues vraiment standards et simples. J'utilise donc agendaEdit pour l'ajout et l'édition d'objets. Mon seul problème, c'est que le AgendaBean doit être vidé avant de pouvoir faire une insertion, sinon l'objet que j'avais en édition auparavant (si je suis passé par la page d'édition) reste en session. J'essaie donc simplement d'exécuter une action particulière (ici AgendaBean.clear()) lorsque je clique sur le lien "Nouvel élément" qui mène à la page d'édition. Cette action n'est cependant que pour ce lien particulier, d'où ma tentative de mettre une action en attribut et de le donner à la composition.

    Je dois dire que je suis encore très peu au clair avec la terminologie JSF et donc que ce qui précède est probablement très mal expliqué. Je m'en excuse d'avance.

    En résumé : comment appeler mon AgendaBean.clear() au moment de cliquer le lien "Nouvel élément" (et seulement ce lien) ?

    Merci d'avance pour toute précision.
    Always code as if the guy maintaining your application is a violent psychopath!
    Site personnel sur la saga Final Fantasy : http://www.final-fantasy.ch

  4. #4
    Rédacteur
    Avatar de romaintaz
    Homme Profil pro
    Java craftsman
    Inscrit en
    Juillet 2005
    Messages
    3 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Java craftsman
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2005
    Messages : 3 790
    Points : 7 275
    Points
    7 275
    Par défaut
    En fait c'est le principe de la composition qui va poser souci.

    Quand tu écris ceci :

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <h:commandButton action="#{monBean.toto}" .../>

    le bouton va générer du code HTML et Javascript pour lui permettre de "savoir" que quand tu cliques dessus, c'est la méthode monBean.toto() qui devra être appelée.

    Une composition est en réalité un sorte de raccourci, qui te permet, avec un tag, de gérer en fait un ensemble de composant. JSF, au moment de générer la page, va "éclater" ta composition dans la page XHTML. Mais pour faire cela, il va devoir évaluer toutes les valeurs spécifiées dans le tag de composition, pour les fournir à la composition. Ainsi, JSF va tenter d'évaluer ces champs comme des chaines de caractères. De ce fait, dans le code :

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <mytags:menuContentLink action="#{monBean.toto}" .../>

    le monBean.toto sera interprété par JSF comme une chaine de caractères et du coup il essaiera d'appeler monBean.getToto(). Cette valeur sera ensuite récupérable dans la composition par le #{action}.

    Mais sur une composition, il n'est du coup pas possible de fournir le nom méthode.

    L'idée la plus simple à mon avis pour résoudre ce problème, est de faire appel à une seule méthode, qui sera définie dans la composition, mais pour laquelle tu donnes un argument définissant quelle véritable méthode sera ensuite appelée par cette méthode de façade.

    Concrètement, ça donnerait quelque chose comme ça :

    D'abord, tu spécifies le type d'action dans actionParam au sein du tag de composition :
    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    <mytags:menuContentLink label="#{msgs.newAgenda}" actionParam="clear" include="/pages/includes/leftNavigationAgenda/agendaEdit.xhtml" />

    Tu passes cet actionParam comme paramètre à ta méthode :

    Code xml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    <rich:panelMenuItem hoverClass="panelMenuItemHover" label="#{label}" action="#{AgendaBean.executeAction}" icon="/resources/images/icons/empty.gif" style="background-color: #F4F4F4;">
        <a4j:actionparam name="include" value="#{include}" assignTo="#{NavigationBean.contentInclude}" />
        <a4j:actionparam name="actionParam" value="#{actionParam}" assignTo="#{AgendaBean.actionParam}"/>
    </rich:panelMenuItem>

    Dans le code Java de AgendaBean, tu fournis le getter/setter pour actionParam, puis dans la méthode executeAction, tu appelles la bonne méthode en fonction de la valeur de actionParam :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    public String executeAction() {
        if ("clear".equals(actionParam)) {
            return clear();
        } else if ("edit".equals(actionParam)) {
     
        } ...
    }
    Ainsi, nul besoin de fournir le nom d'une méthode à ta composition, tu donnes juste un paramètres qui ensuite te permettra, dans le code Java, d'aiguiller ta requête vers la bonne méthode.

    Est-ce plus clair comme ça ?
    Nous sommes tous semblables, alors acceptons nos différences !
    --------------------------------------------------------------
    Liens : Blog | Page DVP | Twitter
    Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
    Critiques : Apache Maven

  5. #5
    Membre confirmé Avatar de Lordsephiroth
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 199
    Points : 494
    Points
    494
    Par défaut
    Bonjour Romain et merci pour ta réponse absolument parfaite.

    J'ai réussi en un tour de main à réaliser ce que tu proposes, et mieux, je pense même avoir compris ce qui se passe et pourquoi

    Je vais facilement pouvoir adapter la solution pour ne plus avoir dans la composition de mon élément de menu un appel direct à AgendaBean.executeAction. Je vais ajouter un bean spécialisé dont la seule utilité sera de contenir ce paramètre actionParam et, lors de l'exécution de executeAction, de faire ce que j'ai besoin de faire (il y aura probablement plusieurs liens de menus qui appelleront clear() sur des beans différents pour réinitialiser des informations de session, et probablement d'autres utilisations similaires).

    Je devrais donc m'en sortir avec ce sorte de bean additionnel contrôlant les actions des éléments de menu.

    Merci infiniment pour les réponses précises, rapides de surcroît.
    Always code as if the guy maintaining your application is a violent psychopath!
    Site personnel sur la saga Final Fantasy : http://www.final-fantasy.ch

  6. #6
    Membre confirmé Avatar de Lordsephiroth
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Mai 2006
    Messages
    199
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : Suisse

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Mai 2006
    Messages : 199
    Points : 494
    Points
    494
    Par défaut
    Hmmm, en fait j'avais oublié un truc... qui a son importance...

    Depuis le bean que je voulais créer comme controller pour ces menus, je n'ai pas la référence sur les beans managés... Je n'arrive donc pas à appeler une fonction clear() sur le bon bean...

    Ca me gène d'avoir dans la composition de mon élément de menu une référence à un Bean particulier (AgendaBean ou nimporte quel autre).

    Je vais réfléchir à une solution, je vois pas bien comment m'en sortir sur le coup.

    Existe-t-il un moyen d'accéder depuis un bean managé à un autre bean managé ?

    Edit : une recherche Google m'a permis de trouver la solution :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    HttpSession session = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true).getAttribute("AgendaBean");
    Mes excuses pour le dernier message que Google m'aurait évité facilement. Mon premier problème était nettement plus complexe à comprendre, je remercie Romain d'avoir pris le temps de me répondre.
    Always code as if the guy maintaining your application is a violent psychopath!
    Site personnel sur la saga Final Fantasy : http://www.final-fantasy.ch

  7. #7
    Rédacteur
    Avatar de romaintaz
    Homme Profil pro
    Java craftsman
    Inscrit en
    Juillet 2005
    Messages
    3 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Java craftsman
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2005
    Messages : 3 790
    Points : 7 275
    Points
    7 275
    Par défaut
    Pas besoin d'aller aussi loin que Google, la FAQ de DVP suffisait pour ce point

    http://javaweb.developpez.com/faq/js...e_session_bean
    Nous sommes tous semblables, alors acceptons nos différences !
    --------------------------------------------------------------
    Liens : Blog | Page DVP | Twitter
    Articles : Hudson | Sonar | Outils de builds Java Maven 3 | Play! 1 | TeamCity| CitConf 2009
    Critiques : Apache Maven

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème d'utilisation de la Servlet Action
    Par Sebastien0104 dans le forum Struts 1
    Réponses: 11
    Dernier message: 05/12/2006, 11h48
  2. utilisation de l'attribut SET dans une selection
    Par stecale dans le forum SQL Procédural
    Réponses: 3
    Dernier message: 24/11/2006, 16h12
  3. [JSCookMenu] attribut action
    Par Yjo dans le forum JSF
    Réponses: 8
    Dernier message: 13/09/2006, 12h21
  4. Récupérer l'attribut action d'un formulaire
    Par boubouh dans le forum Général JavaScript
    Réponses: 9
    Dernier message: 04/02/2006, 15h19
  5. utilisation de l'attribut attr_imgsize dU MODULE Image
    Par vbcasimir dans le forum Modules
    Réponses: 11
    Dernier message: 07/10/2005, 09h30

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo