entre diferencias jsf jsf-2 action commandbutton commandlink

jsf - diferencias - commandbutton action vs actionlistener



commandButton/commandLink/ajax action/listener método no invocado o valor de entrada no establecido/actualizado (9)

A veces, cuando se utiliza <h:commandLink> , <h:commandButton> o <f:ajax> , simplemente no se invoca el método action , actionListener o listener asociado con la etiqueta. O bien, las propiedades del bean no se actualizan con los valores UIInput enviados.

¿Cuáles son las posibles causas y soluciones para esto?


Introducción

Cada vez que un componente UICommand ( <h:commandXxx> , <p:commandXxx> , etc.) no puede invocar el método de acción asociado, o un componente UIInput ( <h:inputXxx> , <p:inputXxxx> , etc.) falla para procesar el los valores enviados y / o actualizan los valores del modelo, y no se ven excepciones y / o advertencias de Google en el registro del servidor, ni tampoco cuando configura un controlador de excepciones ajax según el manejo de excepciones en las solicitudes ajax de JSF , ni cuando establece debajo del parámetro de contexto en web.xml ,

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

y tampoco está viendo ningún error googlable y / o advertencias en la consola de JavaScript del navegador (presione F12 en Chrome / Firefox23 + / IE9 + para abrir el conjunto de herramientas del desarrollador web y luego abra la pestaña Consola ), luego trabaje en la siguiente lista de causas posibles.

Posibles causas

  1. UICommand componentes UICommand y UIInput deben colocarse dentro de un componente UIForm , por ejemplo, <h:form> (y, por lo tanto, no es un simple HTML <form> ), de lo contrario no se puede enviar nada al servidor. UICommand componentes de UICommand tampoco deben tener el atributo type="button" , de lo contrario será un botón muerto que solo es útil para JavaScript en un onclick . Vea 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 .

  2. No puede anidar múltiples componentes UIForm entre sí. Esto es ilegal en HTML. El comportamiento del navegador no está especificado. ¡Cuidado con los archivos incluidos! Puede usar los componentes de UIForm en paralelo, pero no se procesarán entre sí durante el envío. También debes tener cuidado con la "Forma de Dios" antipatrón; asegúrese de no procesar / validar involuntariamente todas las demás entradas (invisibles) en la misma forma (por ejemplo, tener un diálogo oculto con las entradas necesarias en la misma forma). Consulte también ¿Cómo utilizar <h: form> en la página JSF? Forma única? Múltiples formas? Formas anidadas? .

  3. No debería haberse producido ningún error de conversión / validación de valor UIInput . Puede usar <h:messages> para mostrar cualquier mensaje que no muestre ningún componente <h:message> específico de entrada. No olvide incluir el id de <h:messages> en el <f:ajax render> , si lo hubiera, para que se actualice también en las solicitudes de ajax. Vea también h: messages no muestra mensajes cuando se presiona p: commandButton .

  4. Si los componentes UICommand o UIInput se colocan dentro de un componente <h:dataTable> como <h:dataTable> , <ui:repeat> , etc., debe asegurarse de que se conserva exactamente el mismo value del componente iterante durante la fase de solicitud de valores de solicitud el formulario enviar solicitud. JSF lo reiterará para encontrar el enlace / botón pulsado y los valores de entrada enviados. Poner el bean en el alcance de la vista y / o asegurarse de que carga el modelo de datos en @PostConstruct del bean (y, por lo tanto, no en un método de obtención) debe solucionarlo. Vea también Cómo y cuándo debo cargar el modelo desde la base de datos para h: dataTable .

  5. Si los componentes UICommand o UIInput están incluidos por una fuente dinámica como <ui:include src="#{bean.include}"> , debe asegurarse de que se conserva exactamente el mismo valor #{bean.include} durante la vista Tiempo de compilación de la solicitud de envío de 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 que carga el modelo de datos en @PostConstruct del bean (y, por lo tanto, no en un método de obtención) debe solucionarlo. Consulte también ¿Cómo ajax-refresh dynamic incluir contenido en el menú de navegación? (JSF SPA) .

  6. El atributo rendered del componente y todos sus padres y el atributo de test de cualquier <c:if> / <c:when> padre no debe evaluar a false durante la fase de solicitud de valores de solicitud del formulario de solicitud de envío. JSF lo volverá a verificar como parte de la protección contra solicitudes manipuladas / manipuladas. Almacenar las variables responsables de la condición en un bean @ViewScoped o asegurarse de que se está @PostConstruct correctamente la condición en @PostConstruct de un @RequestScoped bean debería solucionarlo. Lo mismo se aplica al atributo disabled del componente, que no debe evaluarse como true durante la fase de solicitud de valores. Vea también la acción JSF CommandButton no invocada y el envío del formulario en el componente procesado condicionalmente no se procesa .

  7. El atributo onclick del componente UICommand y el atributo UIForm componente UIForm no deben devolver false ni provocar un error de JavaScript. En el caso de <h:commandLink> o <f:ajax> tampoco debería haber errores de 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 da como resultado UnEught TypeError en todo lugar .

  8. Si está utilizando Ajax a través de JSF 2.x <f:ajax> o, por ejemplo, PrimeFaces <p:commandXxx> , asegúrese de tener una <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 Ajax. Esto daría como resultado un error de JavaScript como "la mojarra no está definida" o "PrimeFaces no está definida" en la consola JS del navegador. Vea también h: commandLink actionlistener no se invoca cuando se usa con f: ajax y ui: repeat .

  9. Si está utilizando Ajax, asegúrese de que los componentes de interés de UIInput y UICommand estén cubiertos por <f:ajax execute> o, por ejemplo, <p:commandXxx process> , de lo contrario no se ejecutarán / procesarán. Vea también los valores de formulario Enviados no actualizados en el modelo al agregar <f: ajax> a <h: commandButton> y al entender los procesos / actualización de PrimeFaces y JSF f: ajax execute / render .

  10. Si un padre del <h:form> con el botón UICommand ha sido procesado / actualizado previamente por una solicitud ajax proveniente de otro formulario en la misma página, la primera acción siempre fallará. Las segundas y posteriores acciones funcionarán. Esto se debe a un error en el manejo del estado de la vista que se notifica como el problema 790 de la especificación JSF y que actualmente está programado para ser arreglado en JSF 2.3. Para versiones anteriores de JSF, debe especificar explícitamente el ID de <h:form> en el render de <f:ajax> . Vea también h: commandButton / h: commandLink no funciona con el primer clic, funciona solo con el segundo clic .

  11. Si <h:form> tiene enctype="multipart/form-data" configurado para admitir la carga de archivos, debe asegurarse de que está utilizando al menos JSF 2.2, o que el filtro de servlet que es responsable de el análisis de las solicitudes multipart / form-data está configurado correctamente, de lo contrario, FacesServlet no obtendrá ningún parámetro de solicitud y, por lo tanto, no podrá aplicar los valores de solicitud. La forma de configurar un filtro de este tipo depende del componente de carga de archivos que se esté utilizando. Para Tomahawk <t:inputFileUpload> , marque esta respuesta y para PrimeFaces <p:fileUpload> , marque esta respuesta . O, si en realidad no está cargando un archivo, elimine el atributo por completo.

  12. Asegúrese de que el argumento ActionEvent de actionListener es un javax.faces.event.ActionEvent y, por lo tanto, no java.awt.event.ActionEvent , que es lo que la mayoría de los IDE sugieren como primera opción de autocompletar. No tener ningún argumento es incorrecto también si usas actionListener="#{bean.method}" . Si no quieres un argumento en tu método, usa actionListener="#{bean.method()}" . O quizás realmente quieras usar action lugar de actionListener . Véase también Diferencias entre action y actionListener .

  13. Asegúrese de que ningún PhaseListener o cualquier EventListener en la cadena de solicitud-respuesta haya cambiado el ciclo de vida de JSF para omitir la fase de acción de invocación, por ejemplo, llamando a FacesContext#renderResponse() o FacesContext#responseComplete() .

  14. Asegúrese de que ningún Filter o Servlet en la misma cadena de solicitud-respuesta haya bloqueado la solicitud para el FacesServlet alguna manera.

  15. Error en el marco. Por ejemplo, RichFaces tiene un " error de conversión " cuando se utiliza un elemento de IU de rich:calendar con un atributo defaultLabel (o, en algunos casos, un subelemento de rich:placeholder ). Este error evita que se invoque el método de bean cuando no se establece ningún valor para la fecha del calendario. El seguimiento de los errores del marco se puede lograr comenzando con un ejemplo simple y construyendo una copia de seguridad de la página hasta que se descubra el error.

  16. Si está utilizando un p:dialog PrimeFaces o un p:overlayPanel , asegúrese de no ejecutarse en p: la acción del botón de comando no funciona dentro del p: dialog

Consejos de depuración

En caso de que todavía te asustes, es hora de depurar. En el lado del cliente, presione F12 en el navegador web para abrir el conjunto de herramientas para desarrolladores web. Haga clic en la pestaña Consola para ver la conosle de JavaScript. Debe estar libre de cualquier error de JavaScript. La captura de pantalla de abajo es un ejemplo de Chrome que muestra el caso de enviar un botón habilitado <f:ajax> mientras no se ha declarado <h:head> (como se describe en el punto 7 anterior).

Haga clic en la pestaña Red para ver el monitor de tráfico HTTP. Envíe el formulario e investigue si los encabezados de solicitud y los datos del formulario y el cuerpo de respuesta son según las expectativas. La captura de pantalla de abajo es un ejemplo de Chrome que demuestra un envío exitoso de ajax de un formulario simple con un solo <h:inputText> y un solo <h:commandButton> con <f:ajax execute="@form" render="@form"> .

(advertencia: cuando publiques capturas de pantalla de los encabezados de solicitud HTTP como los de un entorno de producción, entonces asegúrate de mezclar / enmascarar 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 al que espera que se le llame durante el procesamiento del formulario enviado. Por ejemplo, en el caso del componente UICommand , sería UICommand#queueEvent() y en el caso del componente UIInput , sería UIInput#validate() . Solo paso a través de la ejecución del código e inspeccione si el flujo y las variables son según las expectativas. Debajo de la captura de pantalla hay un ejemplo del depurador de Eclipse.


Me <h:commandLink> mucho al depurar un problema en el que una acción de <h:commandLink> en richfaces datatable negó a datatable . La tabla solía funcionar en algún momento, pero se detuvo sin ninguna razón aparente. No dejé ninguna piedra sin remover, solo para descubrir que mi rich:datatable estaba usando el rowKeyConverter incorrecto que devolvía nulos que las richfaces usaban felizmente como teclas de fila. Esto evitó que mi acción <h:commandLink> fuera llamada.


Me quedé atascado con este problema y encontré una causa más para este problema. Si no tiene métodos de establecimiento en su bean de respaldo para las propiedades utilizadas en su * .xhtml, entonces simplemente no se invoca la acción.


Mencionaría una cosa más que concierne a p:commandButton !

Cuando usa un p:commandButton para la acción que se debe realizar en el servidor, no puede usar type="button" porque es para los Push Button que se usan para ejecutar javascript personalizado sin causar una solicitud ajax / non-ajax al servidor.

Para este propósito, puede dispensar el atributo de type (el valor predeterminado es "submit" ) o puede usar explícitamente type="submit" .

¡Espero que esto ayude a alguien!


Recientemente me encontré con un problema con un UICommand que no invoca en una aplicación JSF 1.2 utilizando los componentes de IBM Extended Faces.

Tenía un botón de comando en una fila de un datatable (la versión extendida, por lo que <hx:datatable> ) y el UICommand no se activaba desde ciertas filas de la tabla (las filas que no se activaban eran las filas mayores que la fila predeterminada tamaño de la pantalla).

Tenía un componente desplegable para seleccionar el número de filas para mostrar. El valor que respalda este campo estaba en RequestScope . Los datos que respaldan la tabla en sí estaban en una especie de ViewScope (en realidad, temporalmente en SessionScope ).

Si la visualización de la fila se incrementó mediante el control cuyo valor también estaba vinculado al atributo de las rows la tabla de datos, ninguna de las filas mostradas como resultado de este cambio podría disparar el comando UIC cuando se haga clic en él.

Colocar este atributo en el mismo ámbito que los datos de la tabla en sí solucionó el problema.

Creo que se alude a esto en BalusC # 4 anterior, pero no solo el valor de la tabla debe ser Vista o Sesión, sino también el atributo que controla el número de filas para mostrar en esa tabla.


Si bien mi respuesta no es aplicable al 100%, pero la mayoría de los motores de búsqueda encuentran esto como el primer éxito, decidí publicarlo sin embargo:

Si está utilizando PrimeFaces (o alguna API similar) p:commandButton o p:commandLink , es probable que haya olvidado agregar explícitamente process="@this" a sus componentes de comando.

Como lo indica la Guía del usuario de PrimeFaces en la sección 3.18, los valores predeterminados para el process y la update son @form , que se opone bastante a los valores predeterminados que puede esperar de JSF f:ajax o RichFaces, que se execute="@this" y render="@none" respectivamente.

Sólo me tomó un largo tiempo para averiguarlo. (... y creo que es bastante fácil usar valores predeterminados que son diferentes de JSF!)


Si su h:commandLink está dentro de una h:dataTable hay otra razón por la que el h: commandLink podría no funcionar:

El origen de datos subyacente que está vinculado a la h:dataTable también debe estar disponible en el segundo ciclo de vida de JSF que se activa cuando se hace clic en el enlace.

Por lo tanto, si la fuente de datos subyacente tiene un ámbito de solicitud, ¡ h:commandLink no funciona!


También tuve este problema y solo empecé a concentrarme en la causa raíz después de abrir la consola web del navegador. Hasta eso, no pude recibir ningún mensaje de error (incluso con <p:messages> ). La consola web mostró un código de estado HTTP 405 que regresaba de <h:commandButton type="submit" action="#{myBean.submit}"> .

En mi caso, tengo una mezcla de HttpServlet de vainilla que proporciona autenticación OAuth a través de facetas y beans Auth0 y JSF que llevan a cabo las vistas de la aplicación y la lógica empresarial.

Una vez que reformulé mi web.xml y eliminé un servlet de middle man, funcionó "mágicamente".

En pocas palabras, el problema era que el servlet del intermediario utilizaba RequestDispatcher.forward (...) para redirigir desde el entorno HttpServlet al entorno JSF, mientras que se llamaba al servlet antes de redirigir con HttpServletResponse.sendRedirect (.. .).

Básicamente, el uso de sendRedirect () permitió que el "contenedor" de JSF tomara el control, mientras que RequestDispatcher.forward () obviamente no lo era.

Lo que no sé es por qué la faceta pudo acceder a las propiedades del frijol pero no pudo establecerlas, y esto claramente grita por eliminar la mezcla de servlets y JSF, pero espero que esto ayude a alguien a evitar muchas horas de cabeza. a la mesa golpeando.


Una posibilidad más: si el síntoma es que la primera invocación funciona, pero las siguientes no, PrimeFaces 3.x con JSF 2.2, como se detalla aquí: No se envía ViewState .