¿Como funciona?
Cuando se crea / restaura una vista JSF (archivo Facelets / JSP), se generará un árbol de componentes JSF. En ese momento, el tiempo de construcción de la vista , binding
se evalúan todos los atributos ( junto con los id
atributos y los controladores de etiquetas como JSTL ). Cuando es necesario crear el componente JSF antes de agregarlo al árbol de componentes, JSF verificará si el binding
atributo devuelve un componente creado previamente (es decir, no null
) y, si es así, lo utilizará. Si no está creado previamente, JSF creará automáticamente el componente "de la forma habitual" e invocará el binding
atributo de establecimiento detrás con la instancia del componente creado automáticamente como argumento.
En efecto, vincula una referencia de la instancia del componente en el árbol de componentes a una variable de ámbito. Esta información no es visible de ninguna manera en la representación HTML generada del componente en sí. De todos modos, esta información no es relevante para la salida HTML generada. Cuando se envía el formulario y se restaura la vista, el árbol de componentes JSF simplemente se reconstruye desde cero y todos los binding
atributos se volverán a evaluar como se describe en el párrafo anterior. Después de que se vuelva a crear el árbol de componentes, JSF restaurará el estado de la vista JSF en el árbol de componentes.
¡Las instancias de componentes tienen un alcance de solicitud!
Es importante saber y comprender que las instancias de componentes concretos tienen un alcance de solicitud efectivo. Se crean nuevamente en cada solicitud y sus propiedades se llenan con valores del estado de vista JSF durante la fase de restauración de la vista. Por lo tanto, si vincula el componente a una propiedad de un bean de respaldo, entonces el bean de respaldo no debe estar en un alcance más amplio que el alcance de la solicitud. Consulte también el capítulo 3.1.5 de la especificación JSF 2.0 :
3.1.5 Enlaces de componentes
...
Los enlaces de componentes se utilizan a menudo junto con JavaBeans que se instancian dinámicamente a través de la función de creación de Managed Bean (consulte la Sección 5.8.1 “VariableResolver y Default VariableResolver”). Se recomienda encarecidamente que los desarrolladores de aplicaciones coloquen beans gestionados a los que apuntan las expresiones de enlace de componentes en el ámbito de "solicitud". Esto se debe a que colocarlo en el ámbito de la sesión o la aplicación requeriría seguridad de subprocesos, ya que las instancias de UIComponent dependen de que se ejecuten dentro de un solo subproceso. También hay impactos potencialmente negativos en la gestión de la memoria cuando se coloca un enlace de componente en el ámbito de la "sesión".
De lo contrario, las instancias de componentes se comparten entre varias solicitudes, lo que posiblemente da como resultado errores de " ID de componente duplicado " y comportamientos "extraños" porque los validadores, convertidores y oyentes declarados en la vista se vuelven a adjuntar a la instancia de componente existente de solicitudes anteriores. Los síntomas son claros: se ejecutan varias veces, una vez más con cada solicitud dentro del mismo alcance al que está vinculado el componente.
Y, bajo una carga pesada (es decir, cuando varias solicitudes HTTP (subprocesos) diferentes acceden y manipulan la misma instancia de componente al mismo tiempo), tarde o temprano puede enfrentar un bloqueo de la aplicación con, por ejemplo, un subproceso atascado en UIComponent.popComponentFromEL o Java Threads al 100% de utilización de la CPU utilizando richfaces UIDataAdaptorBase y su HashMap interno , o incluso algunos "extraños" IndexOutOfBoundsException
o que ConcurrentModificationException
vienen directamente del código fuente de implementación JSF mientras JSF está ocupado guardando o restaurando el estado de la vista (es decir, el seguimiento de la pila indica saveState()
o restoreState()
métodos y similares).
Usar binding
una propiedad de frijol es una mala práctica
Independientemente, de binding
esta manera, vincular una instancia de componente completa a una propiedad de bean, incluso en un bean con alcance de solicitud, es en JSF 2. un caso de uso bastante raro y generalmente no es la mejor práctica. Indica un olor a diseño. Normalmente se declara componentes en la vista lateral y se unen a sus atributos como el tiempo de ejecución value
, y tal vez otros como styleClass
, disabled
, rendered
, etc, a las propiedades normales de frijol. Luego, simplemente manipule exactamente la propiedad del bean que desea en lugar de tomar todo el componente y llamar al método setter asociado con el atributo.
En los casos en que necesita un componente que se "construyen dinámicamente" basado en un modelo estático, mejor es utilizar vista etiquetas de tiempo de compilación como JSTL , si es necesario en un archivo de etiquetas , en lugar de createComponent()
, new SomeComponent()
, getChildren().add()
y lo que no. Consulte también ¿Cómo refactorizar un fragmento de JSP antiguo a algún equivalente de JSF?
O bien, si un componente necesita ser "prestados de forma dinámica", basada en un modelo dinámico, a continuación, sólo tiene que utilizar un componente iterador ( <ui:repeat>
, <h:dataTable>
, etc.). Consulte también Cómo agregar componentes JSF de forma dinámica .
Los componentes compuestos son una historia completamente diferente. Es completamente legítimo vincular componentes dentro de un <cc:implementation>
al componente de respaldo (es decir, el componente identificado por <cc:interface componentType>
. Vea también ao Dividir java.util.Date en dos campos h: inputText que representan hora y minuto con f: convertDateTime y Cómo implementar una lista dinámica con ¿Un componente compuesto JSF 2.0?
Usar solo binding
en ámbito local
Sin embargo, a veces le gustaría saber sobre el estado de un componente diferente desde dentro de un componente en particular, más que a menudo en casos de uso relacionados con la validación dependiente de acción / valor. Para eso, binding
se puede utilizar el atributo, pero no en combinación con una propiedad de bean. Puede especificar un nombre de variable único en el ámbito de EL local en el binding
atributo así binding="#{foo}"
y el componente está durante la respuesta de renderizado en otro lugar en la misma vista directamente como UIComponent
referencia disponible por #{foo}
. Aquí hay varias preguntas relacionadas en las que se ha utilizado dicha solución en la respuesta:
Ver también:
User.User(), User.getLink(), User.setLink(), User.getValue()
Cuando hago clic en el enlace =User.User(), User.setLink()...