CommandButton/commandLink/ajax acción/método de escucha no invocado o valor de entrada no establecido/actualizado
-
22-09-2019 - |
Pregunta
A veces, al usar <h:commandLink>
, <h:commandButton>
o <f:ajax>
, el action
, actionListener
o listener
El método asociado con la etiqueta simplemente no se invoca.O bien, las propiedades del frijol no se actualizan con el envío. UIInput
valores.
¿Cuáles son las posibles causas y soluciones para esto?
Solución
Introducción
Siempre que un UICommand
componente (<h:commandXxx>
, <p:commandXxx>
, etc) no puede invocar el método de acción asociado, o un UIInput
componente (<h:inputXxx>
, <p:inputXxxx>
, etc.) no puede procesar los valores enviados y/o actualizar los valores del modelo, y no ve ninguna excepción y/o advertencia que se pueda buscar en Google en el registro del servidor, tampoco cuando configura un controlador de excepciones ajax según Manejo de excepciones en solicitudes JSF ajax, ni cuando establece el parámetro de contexto debajo en web.xml
,
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
y tampoco ve ningún error y/o advertencia que se pueda buscar en Google en la consola JavaScript del navegador (presione F12 en Chrome/Firefox23+/IE9+ para abrir el conjunto de herramientas para desarrolladores web y luego abra el Consola pestaña), luego revise la siguiente lista de posibles causas.
Posibles Causas
UICommand
yUIInput
Los componentes deben colocarse dentro de unUIForm
componente, p.e.<h:form>
(y por lo tanto no HTML simple<form>
), de lo contrario no se podrá enviar nada al servidor.UICommand
Los componentes tampoco deben tenertype="button"
atributo, de lo contrario será un botón muerto que sólo es útil para JavaScriptonclick
.Ver también Cómo enviar valores de entrada de formulario e invocar un método en el bean JSF y <h:commandButton> no inicia una devolución de datos.No puedes anidar varios
UIForm
componentes entre sí.Esto es ilegal en HTML.El comportamiento del navegador no está especificado.¡Cuidado con los archivos incluidos!Puedes usarUIForm
componentes en paralelo, pero no se procesarán entre sí durante el envío.También debes tener cuidado con el antipatrón "God Form";asegúrese de no procesar/validar involuntariamente todas las demás entradas (invisibles) en la misma forma (p. ej.tener un cuadro de diálogo oculto con las entradas requeridas en el mismo formulario).Ver también ¿Cómo utilizar <h:form> en la página JSF?¿Forma única?¿Múltiples formas?¿Formularios anidados?.No
UIInput
Debería haberse producido un error de validación/conversión de valor.Puedes usar<h:messages>
para mostrar cualquier mensaje que no se muestre mediante ninguna entrada específica<h:message>
componentes.No olvides incluir elid
de<h:messages>
en el<f:ajax render>
, si lo hay, para que también se actualice en las solicitudes de ajax.Ver también h:messages no muestra mensajes cuando se presiona p:commandButton.Si
UICommand
oUIInput
Los componentes se colocan dentro de un componente iterativo como<h:dataTable>
,<ui:repeat>
, etc, entonces debes asegurarte de que exactamente lo mismovalue
del componente iterativo se conserva durante la fase de aplicación de valores de solicitud de la solicitud de envío del formulario.JSF lo reiterará para encontrar el enlace/botón en el que se hizo clic y los valores de entrada enviados.Poner el bean en el alcance de la vista y/o asegurarse de cargar el modelo de datos en@PostConstruct
del bean (¡y por lo tanto no en un método getter!) debería solucionarlo.Ver también ¿Cómo y cuándo debo cargar el modelo desde la base de datos para h:dataTable?.Si
UICommand
oUIInput
Los componentes son incluidos por una fuente dinámica como<ui:include src="#{bean.include}">
, entonces debes asegurarte de que exactamente lo mismo#{bean.include}
El valor se conserva durante el tiempo de creación de la vista de la solicitud de envío del formulario.JSF lo volverá a ejecutar durante la construcción del árbol de componentes.Poner el bean en el alcance de la vista y/o asegurarse de cargar el modelo de datos en@PostConstruct
del bean (¡y por lo tanto no en un método getter!) debería solucionarlo.Ver también ¿Cómo actualizar ajax de forma dinámica e incluir contenido mediante el menú de navegación?(JSF SPA).El
rendered
atributo del componente y todos sus padres y eltest
atributo de cualquier padre<c:if>
/<c:when>
no debe evaluar afalse
durante la fase de aplicación de valores de solicitud del formulario de envío de solicitud.JSF lo volverá a verificar como parte de la protección contra solicitudes manipuladas o pirateadas.Almacenar las variables responsables de la condición en un@ViewScoped
bean o asegurándose de que esté preinicializando correctamente la condición en@PostConstruct
de un@RequestScoped
Bean debería arreglarlo.Lo mismo se aplica a ladisabled
atributo del componente, que no debe evaluarse comotrue
durante la fase de aplicación de valores de solicitud.Ver también La acción JSF CommandButton no se invoca y El envío del formulario en el componente renderizado condicionalmente no se procesa.El
onclick
atributo de laUICommand
componente y elonsubmit
atributo de laUIForm
El componente no debe regresar.false
o causar un error de JavaScript.Debería haber en caso de<h:commandLink>
o<f:ajax>
Tampoco habrá errores JS visibles en la consola JS del navegador.Por lo general, buscar en Google el mensaje de error exacto ya le dará la respuesta.Ver también Agregar jQuery a PrimeFaces genera errores de tipo no detectados.Si estás usando Ajax a través de JSF 2.x
<f:ajax>
o por ej.caras principales<p:commandXxx>
, asegúrese de tener un<h:head>
en la plantilla maestra en lugar de la<head>
.De lo contrario, JSF no podrá incluir automáticamente los archivos JavaScript necesarios que contienen las funciones de Ajax.Esto daría como resultado un error de JavaScript como "mojarra no está definido" o "PrimeFaces no está definido" en la consola JS del navegador.Ver también h:commandLink actionlistener no se invoca cuando se usa con f:ajax y ui:repeat.Si está utilizando Ajax y los valores enviados terminan siendo
null
, luego asegúrese de que elUIInput
yUICommand
Los componentes de interés están cubiertos por el<f:ajax execute>
o por ej.<p:commandXxx process>
, de lo contrario no serán ejecutados/procesados.Ver también Los valores del formulario enviado no se actualizan en el modelo al agregar <f:ajax> a <h:commandButton> y Comprender el proceso/actualización de PrimeFaces y los atributos de ejecución/renderización JSF f:ajax.Si los valores enviados aún terminan siendo
null
, y está utilizando CDI para administrar beans, luego asegúrese de importar la anotación de alcance del paquete correcto; de lo contrario, CDI usará de manera predeterminada@Dependent
que recrea efectivamente el bean en cada evaluación de la expresión EL.Ver también El bean @SessionScoped pierde alcance y se recrea todo el tiempo, los campos se vuelven nulos y ¿Cuál es el alcance del Bean administrado predeterminado en una aplicación JSF 2?Si un padre del
<h:form>
con elUICommand
El botón se ha renderizado/actualizado previamente mediante una solicitud ajax proveniente de otro formulario en la misma página, entonces la primera acción siempre fallará en JSF 2.2 o anterior.La segunda acción y las siguientes funcionarán.Esto se debe a un error en el manejo del estado de vista que se informa como Problema de especificación JSF 790 y actualmente arreglado en JSF 2.3.Para versiones anteriores de JSF, debe especificar explícitamente el ID del<h:form>
en elrender
del<f:ajax>
.Ver también h:commandButton/h:commandLink no funciona con el primer clic, solo funciona con el segundo clic.Si el
<h:form>
tieneenctype="multipart/form-data"
configurado para admitir la carga de archivos, entonces debe asegurarse de que está utilizando al menos JSF 2.2, o que el filtro de servlet responsable de analizar las solicitudes de datos de formularios/multipartes esté configurado correctamente; de lo contrario, elFacesServlet
terminará sin obtener ningún parámetro de solicitud y, por lo tanto, no podrá aplicar los valores de solicitud.La forma de configurar dicho filtro depende del componente de carga de archivos que se utilice.Para Tomahawk<t:inputFileUpload>
, controlar esta respuesta y para PrimeFaces<p:fileUpload>
, controlar esta respuesta.O, si en realidad no estás cargando ningún archivo, elimina el atributo por completo.Asegúrese de que el
ActionEvent
argumento deactionListener
es unjavax.faces.event.ActionEvent
y por lo tanto nojava.awt.event.ActionEvent
, que es lo que la mayoría de los IDE sugieren como primera opción de autocompletar.No tener argumentos también es incorrecto si usasactionListener="#{bean.method}"
.Si no desea un argumento en su método, utiliceactionListener="#{bean.method()}"
.O tal vez realmente quieras usaraction
en lugar deactionListener
.Ver también Diferencias entre acción y actionListener.Asegúrate de que no
PhaseListener
o cualquierEventListener
en la cadena de solicitud-respuesta ha cambiado el ciclo de vida de JSF para omitir la fase de invocación de acción, por ejemplo llamandoFacesContext#renderResponse()
oFacesContext#responseComplete()
.Asegúrate de que no
Filter
oServlet
en la misma cadena solicitud-respuesta ha bloqueado la solicitud delFacesServlet
de alguna manera.Si está utilizando PrimeFaces
<p:dialog>
o un<p:overlayPanel>
, luego asegúrese de que tengan su propio<h:form>
.Porque JavaScript reubica estos componentes de forma predeterminada al final de HTML<body>
.Entonces, si originalmente estuvieran sentados dentro de un<form>
, entonces ya no se sentarían en un<form>
.Ver también p: la acción del botón de comando no funciona dentro de p: diálogoError en el marco.Por ejemplo, RichFaces tiene un "error de conversión"cuando se utiliza un
rich:calendar
Elemento de interfaz de usuario con undefaultLabel
atributo (o, en algunos casos, unrich:placeholder
subelemento).Este error impide que se invoque el método bean cuando no se establece ningún valor para la fecha del calendario.El seguimiento de errores del marco se puede lograr comenzando con un ejemplo funcional simple y construyendo una copia de seguridad de la página hasta que se descubra el error.
Sugerencias de depuración
En caso de que todavía te quedes atascado, es hora de depurar.En el lado del cliente, presione F12 en el navegador web para abrir el conjunto de herramientas del desarrollador web.Haga clic en el Consola pestaña así que consulte la consola de JavaScript.Debe estar libre de errores de JavaScript.La siguiente captura de pantalla es un ejemplo de Chrome que demuestra el caso de enviar un <f:ajax>
botón habilitado sin tener <h:head>
declarado (como se describe en el punto 7 anterior).
Haga clic en el Red para ver el monitor de tráfico HTTP.Envíe el formulario e investigue si los encabezados de la solicitud, los datos del formulario y el cuerpo de la respuesta cumplen con las expectativas.La siguiente captura de pantalla es un ejemplo de Chrome que demuestra un envío ajax exitoso de un formulario simple con un solo <h:inputText>
y un solo <h:commandButton>
con <f:ajax execute="@form" render="@form">
.
(advertencia:cuando publica capturas de pantalla de encabezados de solicitud HTTP como se muestra arriba desde un entorno de producción, asegúrese de codificar/ofuscar cualquier cookie de sesión en la captura de pantalla para evitar ataques de secuestro de sesión).
En el lado del servidor, asegúrese de que el servidor se inicie en modo de depuración.Coloque un punto de interrupción de depuración en un método del componente JSF de interés que espera que se llame durante el procesamiento del envío del formulario.P.ej.en caso de UICommand
componente, eso sería UICommand#queueEvent()
y en caso de UIInput
componente, eso sería UIInput#validate()
.Simplemente revise la ejecución del código e inspeccione si el flujo y las variables cumplen con las expectativas.La siguiente captura de pantalla es un ejemplo del depurador de Eclipse.
Otros consejos
Si su h:commandLink
está dentro de un h:dataTable
hay otra razón por la h:commandLink
puede que no funcione:
Los datos de código subyacente que está unido a la h:dataTable
también debe estar disponible en el segundo JSF-ciclo de vida que se desencadena cuando se hace clic en el enlace.
Así que si los datos de código subyacente es un ámbito de petición, el h:commandLink
no funciona!
Mientras que mi respuesta no es 100% aplicable, pero la mayoría de los motores de búsqueda encontrar esto como el primer éxito, decidí publicarlo nontheless:
Si está utilizando PrimeFaces (o algún API similar) p:commandButton
o p:commandLink
, lo más probable es que usted ha olvidado de añadir explícitamente process="@this"
a los componentes de su comando.
Guía de la PrimeFaces del usuario declara en la sección 3.18, los valores por defecto para process
y update
son tanto @form
, que se opone más o menos los valores por defecto que puede esperar de f:ajax
JSF simple o RichFaces, que son execute="@this"
y render="@none"
respectivamente.
Sólo me llevó muuuucho tiempo para averiguarlo. (... y yo creo que es más bien unclever a Usar los valores que son diferentes de JSF!)
Me gustaría mencionar una cosa más que p:commandButton
preocupaciones de Primefaces!
Cuando se utiliza un p:commandButton
para la acción que hay que hacer en el servidor, no se puede utilizar type="button"
porque eso es de las teclas que se utiliza para ejecutar javascript personalizada sin causar una ajax / solicitud no Ajax al servidor.
Para este propósito, se puede dispensar el atributo type
(valor por defecto es "submit"
) o puede utilizar de forma explícita type="submit"
.
Esperamos que esto ayude a alguien!
se quedó atascado con este problema a mí mismo y encontró una de las causas más por este problema. Si usted no tiene métodos setter en su bean de respaldo para las propiedades que se utilizan en su * .xhtml, entonces la acción simplemente no es invocado.
Hace poco se encontró con un problema con un UICommand no invocar en una aplicación JSF 1.2 utilizando IBM caras extendidas componentes.
Yo tenía un botón de comando en una fila de una tabla de datos (la versión extendida, por lo <hx:datatable>
) y el UICommand ¿no fuego de ciertas filas de la tabla (las filas que no querían fuego eran las filas superior a la fila de representación por defecto tamaño).
I tenía un componente de menú desplegable para la selección de número de filas que se vea. El valor copias de este campo estaba en RequestScope
. Los datos respaldan la mesa en sí estaba en una especie de ViewScope
(en realidad, temporalmente en SessionScope
).
Si la fila de representación se incrementó a través del mando cuyo valor también fue obligado a rows
atributo de la tabla de datos, ninguna de las filas que se muestran como resultado de este cambio podría disparar el UICommand cuando se hace clic.
La colocación de este atributo en el mismo alcance que los propios datos de mesa fija el problema.
creo que esto se alude en BalusC # 4 arriba, pero no sólo el valor de la tabla necesidad de ser vista o sesión en el ámbito sino también el atributo de controlar el número de filas que se mostrarán en esa mesa.
Yo tenía este problema, así y realmente sólo comenzó a afinar en la raíz después de la apertura de la consola web del navegador. Hasta que eso, yo era incapaz de conseguir cualquier mensaje de error (incluso con <p:messages>
). La consola web mostró un código de estado HTTP 405 al volver de la <h:commandButton type="submit" action="#{myBean.submit}">
.
En mi caso, tengo una mezcla de autenticación OAuth proporcionar vainilla de HttpServlet través facelets y granos que llevan a cabo mis puntos de vista de aplicación y la lógica de negocio Auth0 y JSF.
Una vez que refactorizado mi web.xml, y sacó un servlet-hombre-medio, a continuación, "mágicamente" trabajó.
En pocas palabras, el problema era que el hombre-servlet medio estaba usando RequestDispatcher.forward (...) para redirigir desde el entorno HttpServlet para el medio ambiente JSF mientras que el servlet ser llamado antes de que era reorientando con HttpServletResponse.sendRedirect (...).
Básicamente, usando sendRedirect () permitió la JSF "contenedor" para tomar el control mientras que RequestDispatcher.forward () no era obviamente.
Lo que no sé es por qué el facelet fue capaz de acceder a las propiedades de frijol, pero no los pudo establecer, y esto claramente grita para acabar con la mezcla de servlets y JSF, pero espero que esto ayude a alguien a evitar muchas horas de cabeza a-table-golpes.
Yo tenía un montón de diversión depuración de una cuestión en la acción de un <h:commandLink>
en richfaces
datatable
negó a fuego. La tabla que se utiliza para el trabajo en algún momento, pero se detuvo sin razón aparente. Salí de piedra sin mover, sólo para descubrir que mi rich:datatable
estaba usando el rowKeyConverter
mal que volvió nulos que utilizan richfaces feliz como teclas de la fila. Esto impidió que mi acción <h:commandLink>
de conseguir llamada.
Una posibilidad más: si el síntoma es que los primeros trabajos de invocación, pero los posteriores no lo hacen, puede que esté utilizando PrimeFaces 3.x con JSF 2.2, como se detalla aquí: no se ViewState se envía .
Me fijo mi problema con la colocación de la:
<h:commandButton class="btn btn-danger" value = "Remove" action="#{deleteEmployeeBean.delete}"></h:commandButton>
<h:form>
<h:commandButton class="btn btn-danger" value = "Remove" action="#{deleteEmployeeBean.delete}"></h:commandButton>
</h:form>
<ui:composition>
<h:form id="form1">
<p:dialog id="dialog1">
<p:commandButton value="Save" action="#{bean.method1}" /> <!--Working-->
</p:dialog>
</h:form>
<h:form id="form2">
<p:dialog id="dialog2">
<p:commandButton value="Save" action="#{bean.method2}" /> <!--Not Working-->
</p:dialog>
</h:form>
</ui:composition>
Para resolver;
<ui:composition>
<h:form id="form1">
<p:dialog id="dialog1">
<p:commandButton value="Save" action="#{bean.method1}" /> <!-- Working -->
</p:dialog>
<p:dialog id="dialog2">
<p:commandButton value="Save" action="#{bean.method2}" /> <!--Working -->
</p:dialog>
</h:form>
<h:form id="form2">
<!-- .......... -->
</h:form>
</ui:composition>