commandButton/commandLink / ajax action / listener méthode non invoquée ou valeur d'entrée non définie/mise à jour

parfois, lorsque l'on utilise <h:commandLink> , <h:commandButton> ou <f:ajax> , la méthode action , actionListener ou listener associée à l'étiquette n'est tout simplement pas invoquée. Ou, les propriétés du haricot ne sont pas mises à jour avec les valeurs UIInput soumises.

quelles en sont les causes et les solutions possibles?

315
demandé sur Kukeltje 2010-01-22 19:18:46

9 réponses

Introduction

chaque fois qu'un composant UICommand ( <h:commandXxx> , <p:commandXxx> , etc) ne parvient pas à invoquer la méthode d'action associée, ou un composant UIInput ( <h:inputXxx> , <p:inputXxxx> , etc) ne traite pas les valeurs soumises et/ou ne met pas à jour les valeurs du modèle, et vous ne voyez pas d'exceptions et/ou d'Avertissements googlables dans le journal du serveur, pas plus que lorsque vous configurez un gestionnaire d'exception ajax comme par exemple traitement des exceptions dans les JSF ajax demande , ni lorsque vous définissez le paramètre de contexte dans web.xml ,

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

et vous ne voyez pas non plus d'erreurs et/ou d'Avertissements googlables dans la console JavaScript du navigateur (appuyez sur F12 dans Chrome/Firefox23+/IE9+ pour ouvrir la boîte à outils du développeur web, puis ouvrez la Console onglet), puis travaillez à travers la liste ci-dessous des causes possibles.

causes possibles

    Les composants
  1. UICommand et UIInput doivent être placés à l'intérieur d'un composant UIForm , par exemple <h:form> (et donc pas simplement HTML <form> ), sinon rien ne peut être envoyé au serveur. Les composants UICommand ne doivent pas non plus avoir l'attribut type="button" , sinon ce sera un bouton mort qui n'est utile que pour JavaScript onclick . Voir aussi comment envoyer des valeurs d'entrée de formulaire et invoquer une méthode dans JSF bean et ne prend pas l'initiative d'une publication .

  2. Vous ne pouvez pas imbriquer plusieurs "1519100920," les éléments les uns dans les autres. Cette pratique est illégale en HTML. Le comportement du navigateur n'est pas spécifié. Attention à inclure des fichiers! Vous pouvez utiliser les composants UIForm en parallèle, mais ils ne seront pas traités les uns les autres pendant la soumission. Vous devriez également faire attention avec "forme de Dieu" antipattern; assurez-vous que vous ne faites pas involontairement traiter/valider toutes les autres entrées (invisibles) dans la même forme (par exemple avoir un dialogue caché avec les entrées nécessaires dans la même forme). Voir aussi comment utiliser dans la page JSF? Le formulaire unique? Plusieurs formulaires? Des formes imbriquées? .

  3. No UIInput une erreur de conversion/validation de la valeur aurait dû se produire. Vous pouvez utiliser <h:messages> pour afficher tous les messages qui ne sont pas affichés par une entrée spécifique <h:message> composant. N'oubliez pas d'inclure le id de <h:messages> dans le <f:ajax render> , s'il y a lieu, afin qu'il soit mis à jour sur les requêtes ajax. Voir aussi h: les messages n'affichent pas les messages lorsque p:commandButton est appuyé sur .

  4. si UICommand ou UIInput composants sont placés à l'intérieur d'un composant itératif comme <h:dataTable> , <ui:repeat> , etc, alors vous devez vous assurer que exactement le le même value de la composante itérative est conservé pendant la phase d'application des valeurs de la demande du formulaire soumettre la demande. JSF répétera dessus pour trouver le lien/bouton cliqué et les valeurs d'entrée soumises. Mettre la fève dans le champ de vision et / ou s'assurer que vous chargez le modèle de données dans @PostConstruct de la fève (et donc pas dans une méthode getter!) devrait résoudre le problème. Voir aussi comment et Quand dois-je charger le modèle à partir de la base de données pour h:dataTable .

  5. si UICommand ou UIInput composants sont inclus par une source dynamique telle que <ui:include src="#{bean.include}"> , alors vous devez vous assurer que exactement la même valeur #{bean.include} est conservée pendant le temps de construction de la vue de la requête submit. JSF va le réexécuter pendant la construction de l'arbre des composants. Mettre la fève dans la portée de vue et/ou en s'assurant que vous chargez le modèle de données dans @PostConstruct de la fève (et donc pas dans un getter la méthode!) devrait résoudre le problème. Voir aussi comment faire pour ajax-rafraîchir dynamique inclure le contenu par menu de navigation? (JSF SPA) .

  6. l'attribut rendered du composant et de tous ses parents et l'attribut test de l'un quelconque des parents <c:if> / <c:when> ne doivent pas être évalués à false au cours de la phase appliquer les valeurs de la demande du formulaire soumettre la demande. JSF la revérifiera dans le cadre de la protection contre trafiqué piraté demandes. Stocker les variables responsables de la condition dans un haricot @ViewScoped ou en s'assurant que vous êtes correctement préinitialiser la condition dans @PostConstruct d'un haricot @RequestScoped devrait le fixer. Il en va de même pour l'attribut disabled du composant, qui ne devrait pas être évalué à true pendant la phase appliquer les valeurs de requête. Voir aussi JSF CommandButton action non appelée et soumettre le Formulaire dans certaines conditions le composant Rendu n'est pas traité .

  7. l'attribut onclick du composant UICommand et l'attribut onsubmit du composant UIForm ne doivent pas retourner false ou causer une erreur JavaScript. Dans le cas de <h:commandLink> ou <f:ajax> , il ne doit pas y avoir d'erreurs JS visibles dans la console JS du navigateur. Habituellement googler le message d'erreur exact vous donnera déjà la réponse. Voir aussi L'ajout de jQuery à PrimeFaces donne lieu à une erreur de typographie non corrigée à tous les endroits .

  8. si vous utilisez Ajax via JSF 2.x <f:ajax> ou p.ex. PrimeFaces <p:commandXxx> , assurez-vous que vous avez un <h:head> dans le modèle maître au lieu du <head> . Sinon JSF ne sera pas en mesure d'auto-inclure les fichiers JavaScript nécessaires qui contiennent les fonctions Ajax. Il en résulterait une erreur JavaScript comme "mojarra est pas défini" ou "PrimeFaces n'est pas défini" dans le navigateur JS console. Voir aussi h: commandLink actionlistener n'est pas invoqué lorsqu'il est utilisé avec f:ajax et ui:repeat .

  9. si vous utilisez Ajax, assurez-vous que les composants UIInput et UICommand d'intérêt sont couverts par le <f:ajax execute> ou par exemple <p:commandXxx process> , sinon ils ne seront pas exécutés/traités. Voir Aussi soumis valeurs du formulaire Non mises à jour dans le modèle lors de l'ajout de à et comprendre les PrimeFaces processus/mise à jour et JSF f:ajax exécuter/rendre attributs .

  10. si un parent du <h:form> avec le bouton UICommand est préalablement Rendu/mis à jour par une demande ajax provenant d'un autre formulaire dans la même page, alors la première action sera toujours un échec. Le deuxième et les suivants les actions fonctionneront. Ceci est causé par un bug dans le traitement d'état de vue qui est rapporté comme JSF spec issue 790 et actuellement prévu pour être corrigé dans JSF 2.3. Pour les versions JSF plus anciennes, vous devez spécifier explicitement L'ID du <h:form> dans le render du <f:ajax> . Voir aussi h:commandButton/h:commandLink ne fonctionne pas sur le premier clic, fonctionne seulement sur le deuxième clic .

  11. si le <h:form> a enctype="multipart/form-data" défini afin de prendre en charge le téléchargement de fichiers, alors vous devez vous assurer que vous utilisez au moins JSF 2.2, ou que le filtre servlet qui est responsable de l'analyse des requêtes multipart/form-data est correctement configuré, sinon le FacesServlet finira par ne recevoir aucun paramètre de requête et ne sera donc pas en mesure d'appliquer les valeurs de requête. Comment configurer un tel filtre dépend du composant de téléchargement de fichier utilisé. Pour Tomahawk <t:inputFileUpload> , cochez la case cette réponse et pour PrimeFaces <p:fileUpload> , cochez la case cette réponse . Ou, si vous n'êtes pas en train de télécharger un fichier du tout, alors supprimez l'attribut complètement.

  12. assurez-vous que l'argument ActionEvent de actionListener est un javax.faces.event.ActionEvent et donc pas java.awt.event.ActionEvent , ce qui est ce que la plupart des IDEs suggèrent comme 1ère option autocomplete. N'avoir aucun argument est mal ainsi, si vous utilisez actionListener="#{bean.method}" . Si vous ne voulez pas d'argument dans votre méthode, utilisez actionListener="#{bean.method()}" . Ou peut-être voulez-vous réellement utiliser action au lieu de actionListener . Voir aussi différences entre action et actionListener .

  13. assurez-vous qu'aucun PhaseListener ou aucun EventListener dans la chaîne request-response n'a changé le cycle de vie du JSF pour sauter la phase d'action invoke en appelant par exemple FacesContext#renderResponse() ou FacesContext#responseComplete() .

  14. assurez-vous qu'aucun Filter ou Servlet dans la même chaîne request-response n'a bloqué la requête du FacesServlet d'une manière ou d'une autre.

  15. Bug dans le cadre. Par exemple, RichFaces a une " erreur de conversion "lorsqu'on utilise un élément rich:calendar UI avec un attribut defaultLabel (ou, dans certains cas, un rich:placeholder ). Ce bug empêche la méthode bean d'être invoquée lorsqu'aucune valeur n'est définie pour la date du calendrier. Tracer les bogues de framework peut être accompli en commençant par un exemple de travail simple et en construisant la page de retour jusqu'à ce que le bogue est découvert.

  16. si vous utilisez un PrimeFaces p:dialog ou un p:overlayPanel , assurez-vous que vous ne courez pas dans p: action du bouton de commande ne fonctionne pas à l'intérieur de P: dialog

conseils de débogage

dans le cas où vous STACKS toujours, il est temps de déboguer. Du côté client, appuyez sur F12 dans webbrowser pour ouvrir l'ensemble des outils de développement web. Cliquez sur l'onglet Console pour voir l'onglet JavaScript conosle. Il doit être exempt de toute erreur JavaScript. Ci-dessous screenshot est un exemple de Chrome qui montre le cas de la soumission d'un bouton <f:ajax> activé tandis que ne pas avoir <h:head> déclaré (comme décrit au point 7 ci-dessus).

js console

cliquez sur l'onglet réseau pour voir le moniteur de trafic HTTP. Soumettez le formulaire et vérifiez si les en-têtes de la demande et les données du formulaire et l'organisme de réponse sont conformes aux attentes. Ci-dessous screenshot est un exemple de Chrome qui montre un ajax soumettre avec succès d'un formulaire simple avec un seul <h:inputText> et un seul <h:commandButton> avec <f:ajax execute="@form" render="@form"> .

network monitor

(attention: lorsque vous postez des captures D'écran des en-têtes de requêtes HTTP comme ci-dessus d'un environnement de production, alors assurez-vous de brouiller/brouiller les cookies de session dans la capture d'écran pour éviter les attaques de détournement de session!)

côté serveur, assurez-vous que le serveur est démarré en mode de débogage. Mettez un point de rupture de débogage dans une méthode de la composante JSF d'intérêt que vous vous attendez à être appelé pendant le traitement du formulaire soumettre. Par exemple: dans le cas du composant UICommand , qui serait UICommand#queueEvent() et dans le cas du composant UIInput , qui serait UIInput#validate() . Il suffit de passer par l'exécution du code et d'inspecter si le flux et les variables sont conformes aux attentes. Capture d'écran ci-dessous est un exemple du débogueur D'Eclipse.

debug server

641
répondu BalusC 2018-05-01 10:32:07

si votre h:commandLink se trouve à l'intérieur d'un h:dataTable il y a une autre raison pour laquelle le lien de commande h:pourrait ne pas fonctionner:

la source de données sous-jacente qui est liée au h:dataTable doit également être disponible dans le second cycle de vie JSF qui est déclenché lorsque le lien est cliqué.

donc si la source de données sous-jacente est demandée scoped, le h:commandLink ne fonctionne pas!

51
répondu jbandi 2010-11-08 22:25:06

bien que ma réponse ne soit pas applicable à 100% , mais la plupart des moteurs de recherche trouvent que c'est le premier hit, j'ai décidé de le poster néanmoins:

si vous utilisez PrimeFaces (ou une API similaire) p:commandButton ou p:commandLink , il est probable que vous ayez oublié d'ajouter explicitement process="@this" à vos composants de commande.

comme l'indique le guide de L'utilisateur PrimeFaces dans la section 3.18, les valeurs par défaut pour process et update sont tous les deux @form , qui s'oppose assez fortement aux défauts que vous pourriez attendre de JSF simple f:ajax ou RichFaces, qui sont execute="@this" et render="@none" respectivement.

ça M'a pris du temps pour le savoir. (... et je pense qu'il est assez impur d'utiliser des valeurs par défaut qui sont différentes de JSF!)

25
répondu Kawu 2014-03-06 12:55:01

je voudrais mentionner une chose de plus qui concerne Primefaces p:commandButton !

lorsque vous utilisez un p:commandButton pour l'action qui doit être faite sur le serveur, vous ne pouvez pas utiliser type="button" parce que c'est pour boutons poussoirs qui sont utilisés pour exécuter le JavaScript personnalisé sans causer une requête ajax/non-ajax au serveur.

à cette fin, vous pouvez attribuer l'attribut type (valeur par défaut est "submit" ) ou vous pouvez explicitement utiliser type="submit" .

espérons que cela aidera quelqu'un!

9
répondu akelec 2015-01-03 19:15:10

j'ai récemment rencontré un problème avec un UICommand ne pas invoquer dans une application JSF 1.2 à L'aide de composants IBM Extended Faces.

j'ai eu un bouton de commande sur une rangée d'une datatable (la version étendue, donc <hx:datatable> ) et L'UICommand ne tirerait pas de certaines rangées de la table (les rangées qui ne tireraient pas étaient les rangées plus grandes que la taille d'affichage de rangée par défaut).

j'ai eu un déroulante composant pour sélectionner le nombre de lignes à afficher. La valeur à l'appui de ce champ était dans RequestScope . Les données à l'appui de la table elle-même étaient dans une sorte de ViewScope (en réalité, temporairement dans SessionScope ).

si l'affichage de la rangée était augmenté par le biais de la commande dont la valeur était aussi liée à l'attribut rows du datatable, aucune des rangées affichées à la suite de ce changement ne pouvait tirer sur le UICommand lorsque cliqué.

plaçant cet attribut dans la même portée que les données du tableau lui-même a résolu le problème.

je pense qu'il est fait allusion à cela dans BalusC #4 ci-dessus, mais non seulement la valeur de table doit être vue ou Session scoped mais aussi l'attribut contrôlant le nombre de lignes à afficher sur cette table.

3
répondu Brent C 2015-10-13 18:23:29

a été coincé avec cette question moi-même et a trouvé une cause de plus pour ce problème. Si vous n'avez pas de méthodes setter dans votre support pour les propriétés utilisées dans votre *.xhtml , alors l'action est tout simplement pas invoquée.

2
répondu Syed Mehtab 2013-02-23 10:55:59

j'ai eu ce problème aussi bien et seulement vraiment commencé à aiguiser sur la cause racine après avoir ouvert la console web du navigateur. Jusque là, je n'ai pas pu recevoir de messages d'erreur (même avec <p:messages> ). La console Web montrait un code D'état HTTP 405 qui revenait du <h:commandButton type="submit" action="#{myBean.submit}"> .

dans mon cas, j'ai un mélange de la vanilla HttpServlet fournissant l'authentification OAuth via Auth0 et JSF facelets And beans réalisant mes vues d'application et d'affaires logique.

une fois que j'ai refactoré ma toile.xml, et enlevé un milieu-homme-servlet, il alors "comme par magie" travaillé.

En résumé, le problème était que le moyen-homme-servlet utilisait RequestDispatcher.transmettre.(..) pour rediriger de L'environnement HttpServlet vers L'environnement JSF alors que le servlet appelé avant était redirigé avec HttpServletResponse.sendRedirect(...).

fondamentalement, l'utilisation de sendRedirect () a permis JSF "conteneur" pour prendre le contrôle tandis que RequestDispatcher.forward () ne l'était évidemment pas.

ce que je ne sais pas, c'est pourquoi le facelet a pu accéder aux propriétés des haricots mais n'a pas pu les régler, et cela crie clairement de se débarrasser du mélange de servlets et de JSF, mais j'espère que cela aidera quelqu'un à éviter de nombreuses heures de tête-à-table.

2
répondu Brooks 2017-04-11 16:11:51

j'ai eu beaucoup de plaisir à déboguer un problème où l'action d'un <h:commandLink> dans richfaces datatable a refusé de tirer. La table fonctionnait à un moment donné, mais elle s'est arrêtée sans raison apparente. Je n'ai laissé aucune pierre non retournée, seulement pour découvrir que mon rich:datatable était en utilisant le mauvais rowKeyConverter qui a retourné nulls que richfaces heureusement utilisé comme clés de rangée. Cela a empêché mon action <h:commandLink> de se faire appeler.

0
répondu Mustafa 2017-05-02 19:06:38

une autre possibilité: si le symptôme est que la première invocation fonctionne, mais les suivantes ne fonctionnent pas, vous pouvez utiliser PrimeFaces 3.x avec JSF 2.2, comme détaillé ici: aucun ViewState n'est envoyé .

0
répondu Dave Mulligan 2017-08-17 22:22:41