web-dev-qa-db-de.com

Die Methode commandButton / commandLink / ajax action / listener wurde nicht aufgerufen oder der Eingabewert wurde nicht festgelegt / aktualisiert

Manchmal, wenn <h:commandLink>, <h:commandButton> oder <f:ajax>, die action, actionListener oder listener Methode, die dem Tag zugeordnet sind, werden einfach nicht aufgerufen. Oder die Bean-Eigenschaften werden nicht mit übergebenen UIInput Werten aktualisiert.

Was sind die möglichen Ursachen und Lösungen dafür?

329
Muhammad Hewedy

Einführung

Immer wenn eine UICommand Komponente (<h:commandXxx>, <p:commandXxx> Usw.) die zugehörige Aktionsmethode oder eine UIInput Komponente (<h:inputXxx>, <p:inputXxxx> Usw.) können die übergebenen Werte nicht verarbeiten und/oder die Modellwerte nicht aktualisieren, und im Serverprotokoll werden keine googleablen Ausnahmen und/oder Warnungen angezeigt, auch nicht, wenn Sie eine konfigurieren Ajax-Ausnahmebehandlungsroutine gemäß Ausnahmebehandlung in JSF-Ajax-Anforderungen , oder wenn Sie den folgenden Kontextparameter in web.xml festlegen,

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

außerdem werden in der JavaScript-Konsole des Browsers keine erkennbaren Fehler und/oder Warnungen angezeigt (drücken Sie in Chrome/Firefox23 +/IE9 + die Taste F12, um das Toolset für Webentwickler zu öffnen, und öffnen Sie dann die Registerkarte Console ), dann arbeiten Sie die folgende Liste möglicher Ursachen durch.

Mögliche Ursachen

  1. UICommand und UIInput Komponenten müssen innerhalb einer UIForm Komponente platziert werden, z. <h:form> (Und damit kein reines HTML <form>), Sonst kann nichts an den Server gesendet werden. UICommand Komponenten dürfen auch kein type="button" Attribut haben, da es sich sonst um eine tote Schaltfläche handelt, die nur für JavaScript onclick nützlich ist. Siehe auch So senden Sie Formulareingabewerte und rufen eine Methode in JSF-Bean auf und <h: commandButton> initiiert kein Postback .

  2. Sie können nicht mehrere UIForm Komponenten ineinander verschachteln. Dies ist in HTML illegal. Das Browserverhalten ist nicht spezifiziert. Mit Include-Dateien aufpassen! Sie können UIForm -Komponenten parallel verwenden, aber sie werden sich beim Senden nicht gegenseitig verarbeiten. Sie sollten auch auf das Gegenmuster "God Form" achten. Stellen Sie sicher, dass Sie nicht versehentlich alle anderen (unsichtbaren) Eingaben in derselben Form verarbeiten/validieren (z. B. einen versteckten Dialog mit erforderlichen Eingaben in derselben Form). Siehe auch Verwendung von <h: form> auf einer JSF-Seite? Einzelnes Formular? Mehrere Formulare? Verschachtelte Formulare? .

  3. Es sollte kein Fehler bei der Validierung/Konvertierung von UIInput Werten aufgetreten sein. Sie können <h:messages> Verwenden, um alle Meldungen anzuzeigen, die von keinen eingabespezifischen <h:message> - Komponenten angezeigt werden. Vergessen Sie nicht, das id von <h:messages> In das <f:ajax render> Einzufügen, damit es auch bei Ajax-Anfragen aktualisiert wird. Siehe auch h: messages zeigt keine Meldungen an, wenn p: commandButton gedrückt wird .

  4. Wenn UICommand oder UIInput Komponenten in einer sich wiederholenden Komponente wie <h:dataTable>, <ui:repeat> Usw. platziert sind, müssen Sie sicherstellen, dass genau die gleichen value der iterierenden Komponente wurde während der Phase zum Anwenden von Anforderungswerten der Formularübermittlungsanforderung beibehalten. JSF wiederholt dies, um den angeklickten Link/die angeklickte Schaltfläche und die übermittelten Eingabewerte zu finden. Wenn Sie die Bean in den View-Bereich setzen und/oder sicherstellen, dass Sie das Datenmodell in @PostConstruct Der Bean laden (und somit nicht in eine Getter-Methode!), Sollte dies behoben werden. Siehe auch Wie und wann soll ich das Modell aus der Datenbank für h: dataTable laden .

  5. Wenn UICommand oder UIInput Komponenten in einer dynamischen Quelle wie <ui:include src="#{bean.include}"> Enthalten sind, müssen Sie sicherstellen, dass genau derselbe #{bean.include} Wert beibehalten wird Während der Erstellungszeit der Ansicht des Formulars senden Sie die Anfrage. JSF führt es beim Erstellen des Komponentenbaums erneut aus. Wenn Sie die Bean in den View-Bereich setzen und/oder sicherstellen, dass Sie das Datenmodell in @PostConstruct Der Bean laden (und somit nicht in eine Getter-Methode!), Sollte dies behoben werden. Siehe auch So aktualisieren Sie dynamischen Include-Inhalt über das Navigationsmenü? (JSF SPA) .

  6. Das Attribut rendered der Komponente und aller übergeordneten Elemente sowie das Attribut test eines übergeordneten Elements <c:if>/<c:when> Sollten nicht zu false während der Phase "Werte anwenden" des Formulars "Anfrage senden". JSF überprüft dies im Rahmen des Schutzes vor manipulierten/gehackten Anfragen erneut. Das Speichern der für die Bedingung verantwortlichen Variablen in einem @ViewScoped - Bean oder das ordnungsgemäße Vorinitialisieren der Bedingung in @PostConstruct Eines @RequestScoped - Beans sollte das Problem beheben. Dasselbe gilt für das Attribut disabled der Komponente, das während der Phase zum Anwenden von Anforderungswerten nicht zu true ausgewertet werden sollte. Siehe auch JSF CommandButton-Aktion nicht aufgerufen und Formularübertragung in bedingt gerenderter Komponente wird nicht verarbeitet .

  7. Das onclick -Attribut der UICommand -Komponente und das onsubmit -Attribut der UIForm -Komponente sollten nicht false oder zurückgeben verursachen einen JavaScript-Fehler. Im Falle von <h:commandLink> Oder <f:ajax> Sollten auch keine JS-Fehler in der JS-Konsole des Browsers sichtbar sein. Normalerweise gibt Ihnen das googeln der genauen Fehlermeldung bereits die Antwort. Siehe auch Das Hinzufügen von jQuery zu PrimeFaces führt zu nicht erfassten TypeErrors .

  8. Wenn Sie Ajax über JSF 2.x <f:ajax> Oder z. PrimeFaces <p:commandXxx>, Stellen Sie sicher, dass Sie in der Master-Vorlage ein <h:head> Anstelle des <head> Haben. Andernfalls kann JSF die erforderlichen JavaScript-Dateien, die die Ajax-Funktionen enthalten, nicht automatisch einbinden. Dies würde zu einem JavaScript-Fehler wie "mojarra ist nicht definiert" oder "PrimeFaces ist nicht definiert" in der JS-Konsole des Browsers führen. Siehe auch h: commandLink actionlistener wird bei Verwendung mit f: ajax und ui: repeat nicht aufgerufen .

  9. Wenn Sie Ajax verwenden und die übergebenen Werte am Ende null sind, stellen Sie sicher, dass die UIInput - und UICommand -Komponenten von Interesse durch die <f:ajax execute> Oder zB <p:commandXxx process>, Sonst werden sie nicht ausgeführt/verarbeitet. Siehe auch Übermittelte Formularwerte werden im Modell nicht aktualisiert, wenn <f: ajax> zu <h: commandButton> hinzugefügt wird und Grundlegendes zu PrimeFaces-Prozessen/-Updates und JSF-Attributen f: ajax execute/render =.

  10. Wenn die übergebenen Werte immer noch null sind und Sie CDI zum Verwalten von Beans verwenden, stellen Sie sicher, dass Sie die Bereichsanmerkung aus dem richtigen Paket importieren. Andernfalls wird CDI standardmäßig auf @Dependent, wodurch die Bohne bei jeder einzelnen Auswertung der EL-Expression effektiv neu erstellt wird. Siehe auch @ SessionScoped Bean verliert den Gültigkeitsbereich und wird ständig neu erstellt, Felder werden zu Null und Was ist der Standard-Gültigkeitsbereich für verwaltete Beans in einer JSF 2-Anwendung?

  11. Wenn ein übergeordnetes Element von <h:form> Mit der Schaltfläche UICommand zuvor durch eine Ajax-Anforderung aus einem anderen Formular auf derselben Seite gerendert/aktualisiert wurde, schlägt die erste Aktion in JSF 2.2 immer fehl oder älter. Die zweite und die folgenden Aktionen funktionieren. Dies wird durch einen Fehler in der Ansichtsstatusbehandlung verursacht, der als JSF-Spezifikationsproblem 79 gemeldet wird und derzeit in JSF 2.3 behoben ist. Bei älteren JSF-Versionen müssen Sie die ID des <h:form> Im render des <f:ajax> Explizit angeben. Siehe auch h: commandButton/h: commandLink funktioniert nicht beim ersten Klick, funktioniert nur beim zweiten Klick .

  12. Wenn für <h:form>enctype="multipart/form-data" Festgelegt wurde, um das Hochladen von Dateien zu unterstützen, müssen Sie sicherstellen, dass Sie mindestens JSF 2.2 oder den Servlet-Filter verwenden, der für das Parsen mehrerer Teile verantwortlich ist/Formulardatenanforderungen sind ordnungsgemäß konfiguriert, andernfalls erhält FacesServlet überhaupt keine Anforderungsparameter und kann daher die Anforderungswerte nicht anwenden. Wie ein solcher Filter konfiguriert wird, hängt von der verwendeten Datei-Upload-Komponente ab. Aktivieren Sie für Tomahawk <t:inputFileUpload>diese Antwort und für PrimeFaces <p:fileUpload>diese Antwort . Wenn Sie tatsächlich überhaupt keine Datei hochladen, entfernen Sie das Attribut vollständig.

  13. Stellen Sie sicher, dass das ActionEvent -Argument von actionListener ein javax.faces.event.ActionEvent Und somit kein Java.awt.event.ActionEvent Ist, was die meisten IDEs als erste automatische Vervollständigungsoption vorschlagen. Auch wenn Sie actionListener="#{bean.method}" Verwenden, ist es falsch, kein Argument zu haben. Wenn Sie in Ihrer Methode kein Argument wünschen, verwenden Sie actionListener="#{bean.method()}". Oder vielleicht möchten Sie tatsächlich action anstelle von actionListener verwenden. Siehe auch nterschiede zwischen action und actionListener .

  14. Stellen Sie sicher, dass kein PhaseListener oder irgendein EventListener in der Anforderungs-Antwort-Kette den JSF-Lebenszyklus geändert hat, um die Aktionsphase des Aufrufs zu überspringen, indem Sie beispielsweise FacesContext#renderResponse() oder FacesContext#responseComplete() aufrufen.

  15. Stellen Sie sicher, dass kein Filter oder Servlet in derselben Anfrage-Antwort-Kette die Anfrage für FacesServlet irgendwie blockiert hat.

  16. Wenn Sie PrimeFaces <p:dialog> Oder <p:overlayPanel> Verwenden, stellen Sie sicher, dass sie über einen eigenen <h:form> Verfügen. Da diese Komponenten standardmäßig von JavaScript an das Ende von HTML verschoben werden <body>. Wenn sie also ursprünglich in einem <form> Saßen, würden sie jetzt nicht mehr in einem <form> Sitzen. Siehe auch p: Befehlsschaltflächenaktion funktioniert nicht in p: Dialogfeld

  17. Fehler im Framework. Zum Beispiel hat RichFaces ein " Konvertierungsfehler ", wenn ein rich:calendar - Oberflächenelement mit einem defaultLabel -Attribut (oder in einigen Fällen einem rich:placeholder Unterelement). Dieser Fehler verhindert, dass die Bean-Methode aufgerufen wird, wenn für das Kalenderdatum kein Wert festgelegt ist. Die Verfolgung von Framework-Fehlern kann durchgeführt werden, indem Sie mit einem einfachen Arbeitsbeispiel beginnen und die Seite sichern, bis der Fehler entdeckt wird.

Hinweise zum Debuggen

Wenn Sie immer noch nicht weiterkommen, ist es Zeit für das Debuggen. Drücken Sie auf der Clientseite im Webbrowser die Taste F12, um das Toolset für Webentwickler zu öffnen. Klicken Sie auf die Registerkarte Console , um das JavaScript-Fenster zu öffnen. Es sollte frei von JavaScript-Fehlern sein. Der folgende Screenshot zeigt ein Beispiel aus Chrome, das den Fall demonstriert, dass eine <f:ajax> - aktivierte Schaltfläche gesendet wird, ohne dass <h:head> Deklariert wurde (wie in Punkt 7 oben beschrieben).

js console

Klicken Sie auf die Registerkarte Netzwerk , um den HTTP-Verkehrsmonitor anzuzeigen. Senden Sie das Formular und prüfen Sie, ob die Anforderungsheader und Formulardaten sowie der Antworttext den Erwartungen entsprechen. Der folgende Screenshot zeigt ein Beispiel aus Chrome, das eine erfolgreiche Ajax-Übermittlung eines einfachen Formulars mit einem einzelnen <h:inputText> Und einem einzelnen <h:commandButton> Mit <f:ajax execute="@form" render="@form">.

network monitor

(Warnung: Wenn Sie Screenshots aus HTTP-Anforderungsheader wie oben aus einer Produktionsumgebung veröffentlichen, stellen Sie sicher, dass Sie Sitzungscookies im Screenshot verschlüsseln/verschleiern, um Angriffe auf Sitzungshijacking zu vermeiden!)

Stellen Sie auf der Serverseite sicher, dass der Server im Debug-Modus gestartet wurde. Fügen Sie einen Debug-Haltepunkt in eine Methode der gewünschten JSF-Komponente ein, von der Sie erwarten, dass sie während der Verarbeitung des Formulars submit aufgerufen wird. Z.B. im Falle einer UICommand Komponente wäre das UICommand#queueEvent() und im Falle einer UIInput Komponente wäre das UIInput#validate() . Führen Sie einfach die Codeausführung durch und überprüfen Sie, ob der Ablauf und die Variablen den Erwartungen entsprechen. Der folgende Screenshot zeigt ein Beispiel aus dem Debugger von Eclipse.

debug server

661
BalusC

Wenn sich Ihr h:commandLink In einem h:dataTable Befindet, funktioniert der h:commandLink Möglicherweise aus einem anderen Grund nicht:

Die zugrunde liegende Datenquelle, die an h:dataTable Gebunden ist, muss auch im zweiten JSF-Lebenszyklus verfügbar sein, der beim Klicken auf den Link ausgelöst wird.

Wenn die zugrunde liegende Datenquelle einen Anforderungsbereich hat, funktioniert h:commandLink Nicht!

52
jbandi

Meine Antwort ist zwar nicht zu 100% zutreffend, aber die meisten Suchmaschinen finden sie als ersten Treffer. Trotzdem habe ich beschlossen, sie zu posten:

Wenn Sie PrimeFaces (oder eine ähnliche API) p:commandButton Oder p:commandLink Verwenden, haben Sie wahrscheinlich vergessen, process="@this" Explizit zu Ihrem Konto hinzuzufügen Befehlskomponenten.

Wie im PrimeFaces-Benutzerhandbuch in Abschnitt 3.18 angegeben, lauten die Standardeinstellungen für process und update beide @form, Was den Standardeinstellungen von einfachem JSF f:ajax Oder RichFaces, die execute="@this" Bzw. render="@none" Sind.

Ich habe lange gebraucht, um es herauszufinden. (... und ich denke, es ist ziemlich ungewöhnlich, andere Standardeinstellungen als JSF zu verwenden!)

28
Kawu

Ich möchte noch eine Sache erwähnen, die Primefaces p:commandButton Betrifft!

Wenn Sie einen p:commandButton Für die Aktion verwenden, die auf dem Server ausgeführt werden muss, können Sie type="button" Nicht verwenden, da dies für ist Drück Knöpfe Diese werden verwendet, um benutzerdefiniertes Javascript auszuführen, ohne eine Ajax-/Nicht-Ajax-Anforderung an den Server auszulösen.

Zu diesem Zweck können Sie das type -Attribut ausgeben (Standardwert ist "submit") Oder Sie können explizit type="submit" Verwenden.

Hoffe das wird jemandem helfen!

9
akelec

Ich bin kürzlich auf ein Problem mit einem UICommand gestoßen, der in einer JSF 1.2-Anwendung mit IBM Extended Faces Components nicht aufgerufen wurde.

Ich hatte eine Befehlsschaltfläche in einer Zeile einer Datentabelle (die erweiterte Version, also <hx:datatable>) und der UICommand wurden nicht aus bestimmten Zeilen der Tabelle ausgelöst (die Zeilen, die nicht ausgelöst wurden, waren die Zeilen, die größer als die Standardzeilenanzeigegröße waren).

Ich hatte eine Dropdown-Komponente zum Auswählen der Anzahl der anzuzeigenden Zeilen. Der Wert für dieses Feld war RequestScope. Die Daten, die die Tabelle selbst stützten, befanden sich in einer Art ViewScope (in Wirklichkeit vorübergehend in SessionScope).

Wenn die Zeilenanzeige über das Steuerelement erhöht wurde, dessen Wert auch an das Attribut rows der Datentabelle gebunden war, konnte keine der als Ergebnis dieser Änderung angezeigten Zeilen den UICommand auslösen, wenn auf sie geklickt wurde.

Das Problem wurde behoben, indem dieses Attribut in denselben Bereich wie die Tabellendaten gesetzt wurde.

Ich denke, dass dies in BalusC # 4 oben angedeutet ist, aber nicht nur der Tabellenwert musste View- oder Session-bezogen sein, sondern auch das Attribut, das die Anzahl der Zeilen steuert, die in dieser Tabelle angezeigt werden sollen.

3
Brent C

Ich habe mich mit diesem Problem beschäftigt und eine weitere Ursache für dieses Problem gefunden. Wenn Ihre Backing-Bean keine Setter-Methoden für die in Ihrer * .xhtml-Datei verwendeten Eigenschaften enthält, wird die Aktion einfach nicht aufgerufen.

3
Syed Mehtab

Ich hatte auch dieses Problem und begann erst nach dem Öffnen der Webkonsole des Browsers, die eigentliche Ursache herauszufinden. Bis dahin konnte ich keine Fehlermeldungen erhalten (auch mit <p:messages>). Die Webkonsole zeigte einen HTTP 405-Statuscode an, der vom <h:commandButton type="submit" action="#{myBean.submit}"> Zurückkommt.

In meinem Fall habe ich eine Mischung aus Vanilla HttpServlets, die OAuth Authentifizierung über Auth0- und JSF-Facelets und -Beans bereitstellen und meine Anwendungsansichten und Geschäftslogik ausführen.

Nachdem ich meine web.xml überarbeitet und ein Middle-Man-Servlet entfernt hatte, funktionierte es "magisch".

Im Endeffekt bestand das Problem darin, dass das Middle-Man-Servlet RequestDispatcher.forward (...) verwendete, um von der HttpServlet-Umgebung zur JSF-Umgebung umzuleiten, während das Servlet, das vor der Umleitung aufgerufen wurde, mit HttpServletResponse.sendRedirect (.. .).

Die Verwendung von sendRedirect () ermöglichte es dem JSF-Container, die Kontrolle zu übernehmen, während dies bei RequestDispatcher.forward () offensichtlich nicht der Fall war.

Was ich nicht weiß, ist, warum das Facelet auf die Bean-Eigenschaften zugreifen konnte, diese aber nicht festlegen konnte. Dies spricht eindeutig dafür, die Mischung aus Servlets und JSF zu beseitigen. to-table-banging.

2
Brooks

Eine weitere Möglichkeit: Wenn das Symptom ist, dass der erste Aufruf funktioniert, nachfolgende jedoch nicht, verwenden Sie möglicherweise PrimeFaces 3.x mit JSF 2.2, wie hier beschrieben: Es wird kein ViewState gesendet .

0
Dave Mulligan

Ich hatte viel Spaß beim Debuggen eines Problems, bei dem ein <h:commandLink> 's Aktion in richfacesdatatable lehnte ab zu feuern. Der Tisch arbeitete zu einem bestimmten Zeitpunkt, blieb jedoch ohne ersichtlichen Grund stehen. Ich habe nichts unversucht gelassen, nur um herauszufinden, dass mein rich:datatable verwendete das falsche rowKeyConverter, das Nullen zurückgab, die richfaces gerne als Zeilenschlüssel verwendeten. Dies verhinderte mein <h:commandLink> Aktion vor dem Aufruf.

0
Mustafa