commandButton / commandLink / ajax action / metodo listener non richiamato o valore di input non impostato / aggiornato

A volte, quando si utilizza , o , il metodo action , actionListener o listener associato al tag non viene semplicemente richiamato. Oppure, le proprietà del bean non vengono aggiornate con i valori UIInput inviati.

Quali sono le possibili cause e soluzioni per questo?

introduzione

Ogni volta che un componente UICommand ( , , ecc.) Non riesce a richiamare il metodo di azione associato o un componente UIInput ( , , ecc.) Non riesce a elaborare il inviato valori e / o aggiorna i valori del modello, e non si vedono eccezioni googlable e / o avvisi nel log del server, anche quando non si configura un gestore di eccezioni ajax come per la gestione delle eccezioni nelle richieste Ajax JSF , né quando si imposta sotto il parametro context in web.xml ,

  javax.faces.PROJECT_STAGE Development  

e inoltre non visualizzi alcun errore o avviso googlable nella console JavaScript del browser (premi F12 in Chrome / Firefox23 + / IE9 + per aprire il set di strumenti di sviluppo Web e quindi apri la scheda Console ), quindi consulta l’elenco sottostante di possibili cause.

Cause possibili

  1. UICommand componenti UICommand e UIInput devono essere posizionati all’interno di un componente UIForm , ad esempio (e quindi non HTML

    ), altrimenti non è ansible inviare nulla al server. UICommand componenti UICommand non devono avere attributo type="button" , altrimenti sarà un dead button che è utile solo per JavaScript onclick . Vedi anche Come inviare i valori di input del modulo e richiamare un metodo nel bean JSF e non avvia un postback .

  2. Non è ansible nidificare più componenti UIForm uno nell’altro. Questo è illegale in HTML. Il comportamento del browser non è specificato. Fai attenzione con i file inclusi! È ansible utilizzare i componenti UIForm in parallelo, ma non si elaborano a vicenda durante l’invio. Dovresti anche fare attenzione con “God Form” antipattern; assicurati di non processare / convalidare involontariamente tutti gli altri input (invisibili) nella stessa forma (ad es. avere una finestra di dialogo nascosta con gli input richiesti nella stessa forma). Vedi anche Come usare nella pagina JSF? Forma singola? Più forms? Forme annidate? .

  3. Non si UIInput verificato alcun UIInput convalida / conversione del valore UIInput . Puoi usare per mostrare tutti i messaggi che non sono mostrati da nessun componente specifico per l’input. Non dimenticare di includere l’ id di in , se ce ne sono, in modo che venga aggiornato anche su richieste ajax. Vedi anche h: i messaggi non visualizzano i messaggi quando viene premuto p: commandButton .

  4. Se i componenti UICommand o UIInput sono posizionati all’interno di un componente come , , ecc, allora è necessario assicurarsi che lo stesso value del componente iterativo sia stato conservato durante la fase dei valori della richiesta di applicazione di il modulo invia richiesta. JSF ripeterà su di esso per trovare il link / pulsante cliccato e i valori di input inviati. Mettere il bean nell’ottica della vista e / o assicurarti di caricare il modello di dati in @PostConstruct del bean (e quindi non in un metodo getter!) Dovrebbe risolverlo. Vedi anche Come e quando dovrei caricare il modello dal database per h: dataTable .

  5. Se i componenti UICommand o UIInput sono inclusi da una fonte dynamic come , allora devi assicurarti che lo stesso identico #{bean.include} valore sia conservato durante la visualizzazione tempo di compilazione del modulo inviare richiesta. JSF lo rieseguirà durante la costruzione dell’albero dei componenti. Mettere il bean nell’ottica della vista e / o assicurarti di caricare il modello di dati in @PostConstruct del bean (e quindi non in un metodo getter!) Dovrebbe risolverlo. Vedi anche Come ajax-refresh dinamico include il contenuto dal menu di navigazione? (SPA JSF) .

  6. L’attributo rendered del componente e di tutti i suoi genitori e l’attributo test di qualsiasi genitore / non deve essere valutato su false durante la fase di richiesta dei valori della richiesta di invio del modulo. JSF lo ricontrollerà come parte della salvaguardia contro richieste manomesse / violate. Memorizzare le variabili responsabili della condizione in un bean @ViewScoped o assicurarti di preinitializzare correttamente la condizione in @PostConstruct di un bean @RequestScoped dovrebbe risolverlo. Lo stesso vale per l’attributo disabled del componente, che non dovrebbe true su true durante l’applicazione della fase dei valori di richiesta. Vedere anche l’ azione CommandButton JSF non invocata e l’ invio del modulo nel componente con rendering condizionale non viene elaborato .

  7. L’attributo onclick del componente UICommand e l’attributo onsubmit del componente UIForm non devono restituire false o causare un errore JavaScript. In caso di o dovrebbe anche non essere visibile nessun errore JS nella console JS del browser. Solitamente googling il messaggio di errore esatto ti darà già la risposta. Vedi anche Aggiunta di jQuery ai risultati PrimeFaces in Uncaught TypeError su tutto il luogo .

  8. Se stai utilizzando Ajax tramite JSF 2.x o ad es. PrimeFaces , assicurati di avere nel template principale invece di . In caso contrario, JSF non sarà in grado di includere automaticamente i file JavaScript necessari che contengono le funzioni Ajax. Ciò comporterebbe un errore JavaScript come “mojarra non è definito” o “PrimeFaces non è definito” nella console JS del browser. Vedi anche h: commandLink actionlistener non viene invocato quando viene utilizzato con f: ajax e ui: repeat .

  9. Se stai usando Ajax, assicurati che i componenti UIInput e UICommand di interesse siano coperti da o, ad esempio, , altrimenti non saranno eseguiti / elaborati. Vedi anche Valori di modulo inviati non aggiornati nel modello quando si aggiunge a e Understanding PrimeFaces process / update e JSF f: ajax esegue / rende attributi .

  10. Se un genitore del con il pulsante UICommand è preventivamente reso / aggiornato da una richiesta UICommand proveniente da un altro modulo nella stessa pagina, la prima azione fallirà sempre. La seconda e le successive azioni funzioneranno. Questo è causato da un bug nella gestione dello stato di visualizzazione che viene segnalato come problema 790 della JSF e attualmente programmato per essere risolto in JSF 2.3. Per le versioni JSF precedenti, è necessario specificare esplicitamente l’ID di nel render di . Vedi anche h: commandButton / h: commandLink non funziona al primo clic, funziona solo al secondo clic .

  11. Se il ha enctype="multipart/form-data" impostato per supportare il caricamento di file, allora devi assicurarti di utilizzare almeno JSF 2.2, o che il filtro servlet responsabile di l’analisi delle richieste multipart / form-data è configurata correttamente, altrimenti FacesServlet finirà per non ricevere alcun parametro di richiesta e quindi non sarà in grado di applicare i valori della richiesta. Come configurare un tale filtro dipende dal componente di upload del file utilizzato. Per Tomahawk , controlla questa risposta e per PrimeFaces , controlla questa risposta . Oppure, se in realtà non stai caricando un file, rimuovi l’attributo.

  12. Assicurati che l’argomento ActionEvent di actionListener sia javax.faces.event.ActionEvent e quindi non java.awt.event.ActionEvent , che è quello che la maggior parte degli IDE suggerisce come prima opzione di completamento automatico. Non avere argomenti è sbagliato se si utilizza actionListener="#{bean.method}" . Se non vuoi un argomento nel tuo metodo, usa actionListener="#{bean.method()}" . O forse in realtà vuoi usare l’ action invece di actionListener . Vedi anche Differenze tra azione e azioneListener .

  13. Assicurarsi che nessun PhaseListener o EventListener nella catena richiesta-risposta abbia modificato il ciclo di vita JSF per saltare la fase di azione di richiamo, ad esempio chiamando FacesContext#renderResponse() o FacesContext#responseComplete() .

  14. Assicurati che nessun Filter o Servlet nella stessa catena di richieste-risposte abbia bloccato la richiesta del FacesServlet qualche modo.

  15. Bug nel framework. Ad esempio, RichFaces ha un ” errore di conversione ” quando si utilizza un elemento dell’interfaccia utente rich:calendar con un attributo defaultLabel (o, in alcuni casi, un elemento secondario rich:placeholder ). Questo bug impedisce il richiamo del metodo bean quando non è impostato alcun valore per la data del calendario. Tracciare i bug del framework può essere realizzato iniziando con un semplice esempio di lavoro e costruendo il backup della pagina fino a quando il bug non viene scoperto.

  16. Se stai usando una p:dialog PrimeFaces p:dialog o un p:overlayPanel , assicurati di non eseguire l’ azione p: commandbutton non funziona all’interno di p: dialog

Suggerimenti per il debug

Nel caso in cui si stia ancora, è il momento di eseguire il debug. Dal lato client, premi F12 in webbrowser per aprire il set di strumenti di sviluppo web. Fare clic sulla scheda Console, quindi consultare il dizionario JavaScript. Dovrebbe essere privo di errori JavaScript. Sotto lo screenshot è un esempio di Chrome che dimostra il caso di inviare un pulsante abilitato senza avere dichiarato (come descritto al punto 7 sopra).

console js

Fare clic sulla scheda Rete per vedere il monitoraggio del traffico HTTP. Invia il modulo e verifica se le intestazioni delle richieste e i dati del modulo e il corpo della risposta sono conformi alle aspettative. Sotto lo screenshot è un esempio di Chrome che dimostra un invio ajax di successo di un semplice modulo con un singolo e un singolo con .

monitor di rete

(attenzione: quando pubblichi screenshot da intestazioni di richieste HTTP come sopra da un ambiente di produzione, assicurati di scramble / offuscare eventuali cookie di sessione nello screenshot per evitare attacchi di dirottamento di sessione!)

Sul lato server, assicurarsi che il server sia avviato in modalità debug. Metti un punto di interruzione del debug in un metodo del componente JSF di interesse che ti aspetti di chiamare durante l’elaborazione del modulo submit. Ad esempio, nel caso del componente UICommand , sarebbe UICommand#queueEvent() e nel caso del componente UIInput , sarebbe UIInput#validate() . Basta passare attraverso l’esecuzione del codice e controllare se il stream e le variabili sono come da aspettative. Qui sotto lo screenshot è un esempio del debugger di Eclipse.

server di debug

Se h:commandLink è all’interno di h:dataTable esiste un’altra ragione per cui h: commandLink potrebbe non funzionare:

La sorgente dati sottostante associata a h:dataTable deve essere disponibile anche nel secondo ciclo di vita JSF triggersto quando viene fatto clic sul collegamento.

Quindi, se l’origine dati sottostante è a richiesta, h:commandLink non funziona!

Sebbene la mia risposta non sia applicabile al 100%, ma la maggior parte dei motori di ricerca trova questo come il primo hit, ho deciso di postarlo comunque:

Se utilizzi PrimeFaces (o API simili) p:commandButton o p:commandLink , è probabile che tu abbia dimenticato di aggiungere in modo esplicito process="@this" ai tuoi componenti di comando.

Come afferma la Guida dell’utente di PrimeFaces nella sezione 3.18, i valori predefiniti per process e update sono entrambi @form , che si oppone in modo @form ai valori predefiniti che ci si potrebbero aspettare da JSF f:ajax o RichFaces, che sono execute="@this" e render="@none" rispettivamente.

Mi ci è voluto un po ‘di tempo per scoprirlo. (… e penso che sia piuttosto scortese usare i valori di default che sono diversi da JSF!)

Vorrei menzionare un’altra cosa che riguarda p:commandButton di Primefaces!

Quando si utilizza p:commandButton per l’azione che deve essere eseguita sul server, non è ansible utilizzare type="button" perché è per i pulsanti che vengono utilizzati per eseguire javascript personalizzati senza causare una richiesta ajax / non-ajax al server.

A tale scopo, è ansible dispensare l’attributo type (il valore predefinito è "submit" ) oppure è ansible utilizzare esplicitamente type="submit" .

Spero che questo aiuti qualcuno!

Recentemente ho riscontrato un problema con un UICommand che non stava invocando in un’applicazione JSF 1.2 utilizzando IBM Faces Components.

Avevo un pulsante di comando su una riga di un datatable (la versione estesa, quindi ) e l’UICommand non sparava da certe righe dalla tabella (le righe che non avrebbero sparato erano le file maggiori della riga predefinita dimensione del display).

Ho avuto un componente a discesa per selezionare il numero di righe da visualizzare. Il valore che supportava questo campo era in RequestScope . I dati a supporto del tavolo stesso erano in una sorta di ViewScope (in realtà, temporaneamente in SessionScope ).

Se la visualizzazione della riga è stata aumentata tramite il controllo, il valore è stato anche associato all’attributo rows del datatable, nessuna delle righe visualizzate come risultato di questa modifica potrebbe triggersre UICommand quando viene fatto clic.

Il posizionamento di questo attributo nello stesso ambito dei dati della tabella ha risolto il problema.

Penso che questo sia accennato in BalusC # 4 sopra, ma non solo il valore della tabella deve essere vista o Session scope ma anche l’attributo che controlla il numero di righe da mostrare su quella tabella.

Sono rimasto bloccato con questo problema me stesso e ho trovato una causa in più per questo problema. Se non hai i metodi setter nel tuo backing bean per le proprietà usate nel tuo * .xhtml, allora l’azione non viene semplicemente invocata.

Ho avuto anche questo problema e ho iniziato davvero a perfezionare la causa principale dopo aver aperto la console web del browser. Fino a quel momento, non ero in grado di ricevere alcun messaggio di errore (anche con ). La console Web ha mostrato un codice di stato HTTP 405 proveniente da .

Nel mio caso, ho un mix di vanute HttpServlet che fornisce l’autenticazione OAuth tramite facelet e bean di Auth0 e JSF che eseguono le mie visualizzazioni di applicazioni e la logica di business.

Una volta refactored il mio web.xml e rimosso un servlet del middle-man, allora “magicamente” ha funzionato.

In conclusione, il problema era che il servlet middle man stava usando RequestDispatcher.forward (…) per redirect dall’ambiente HttpServlet all’ambiente JSF mentre il servlet che veniva chiamato prima stava reindirizzando con HttpServletResponse.sendRedirect (.. .).

Fondamentalmente, l’uso di sendRedirect () consentiva al “contenitore” JSF di assumere il controllo mentre Ovviamente RequestDispatcher.forward () non lo era.

Quello che non so è perché il facelet è stato in grado di accedere alle proprietà del bean ma non è stato in grado di impostarle, e questo chiaramente urla per eliminare il mix di servlet e JSF, ma spero che questo aiuti qualcuno a evitare molte ore di head- to-table-banging.

Mi sono divertito un sacco a fare il debug di un problema in cui un’azione di in richfaces rifiutava di sparare. Il tavolo funzionava a un certo punto ma si fermava senza una ragione apparente. Non ho lasciato nulla di intentato, solo per scoprire che il mio rich:datatable stava usando la rowKeyConverter errata rowKeyConverter che restituiva valori null che i facsimilmente utilizzavano come chiavi di riga. Ciò ha impedito il dell’azione .

Un’altra possibilità: se il sintomo è che la prima invocazione funziona, ma quelli successivi no, potresti utilizzare PrimeFaces 3.x con JSF 2.2, come descritto qui: non viene inviato alcun ViewState .