¿Por qué JSF guarda el estado de los componentes de la interfaz de usuario en el servidor?
¿Hasta qué momento JSF guarda el estado de los componentes de la interfaz de usuario en el lado del servidor y cuándo exactamente se elimina la información de estado del componente de la interfaz de usuario de la memoria del servidor? A medida que un usuario que ha iniciado sesión en la aplicación navega por las páginas, ¿se seguirá acumulando el estado de los componentes en el servidor?
¡ No entiendo cuál es el beneficio de mantener el estado de los componentes de la interfaz de usuario en el servidor! ¿No es suficiente pasar directamente los datos validados/convertidos a beans administrados? ¿Puedo o debería intentar evitarlo?
¿No consume eso demasiada memoria en el lado del servidor si hay miles de sesiones de usuarios simultáneas? Tengo una aplicación donde los usuarios pueden publicar blogs sobre ciertos temas. Estos blogs son bastante grandes. Cuando haya una publicación o una solicitud para ver los blogs, ¿se guardarán los datos de esta gran página como parte del estado de los componentes? Esto consumiría demasiada memoria. ¿No es esto una preocupación?
Actualización 1:
Ahora ya no es necesario guardar el estado mientras se usa JSF. Se encuentra disponible para su uso una implementación JSF sin estado de alto rendimiento. Consulte este blog y esta pregunta para obtener detalles y debates relevantes. Además, existe un problema abierto que se debe incluir en las especificaciones de JSF, una opción para proporcionar un modo sin estado para JSF. (PD: considere votar por los problemas este y este si esta es una característica útil para usted).
Actualización 2 (24-02-2013):
¡ Es una gran noticia que Mojarra 2.1.19 esté disponible con modo sin estado !
Mira aquí:
http://weblogs.java.net/blog/mriem/archive/2013/02/08/jsf-going-stateless?force=255
http://java.net/jira/browse/JAVASERVERFACES-2731
http://balusc.blogspot.de/2013/02/stateless-jsf.html
¿Por qué JSF necesita guardar el estado de los componentes de la interfaz de usuario en el lado del servidor?
Porque HTTP no tiene estado y JSF tiene estado. El árbol de componentes JSF está sujeto a cambios dinámicos (programáticos). JSF simplemente necesita saber el estado exacto en el que se encontraba cuando el formulario se mostró al usuario final, para que pueda procesar con éxito todo el ciclo de vida de JSF en función de la información proporcionada por el árbol de componentes JSF original cuando el formulario se envió nuevamente a el servidor. El árbol de componentes proporciona información sobre los nombres de los parámetros de solicitud, los convertidores/validadores necesarios, las propiedades del bean administrado vinculado y los métodos de acción. Cuando, por ejemplo, el atributo disabled
o readonly
de un componente de entrada se cambia mediante programación true
y esta información se guarda en el estado de vista, esto juega un papel importante como protección contra solicitudes manipuladas.
¿Hasta qué momento JSF guarda el estado de los componentes de la interfaz de usuario en el lado del servidor y cuándo exactamente se elimina la información de estado del componente de la interfaz de usuario de la memoria del servidor?
Esas dos preguntas parecen reducirse a lo mismo. De todos modos, esto es específico de la implementación y también depende de si el estado se guarda en el servidor o en el cliente. Una implementación un poco decente lo eliminará cuando haya caducado o cuando la cola esté llena. Mojarra, por ejemplo, tiene un límite predeterminado de 15 vistas lógicas cuando el guardado de estado está configurado en sesión. Esto se puede configurar con el siguiente parámetro de contexto en web.xml
:
<context-param>
<param-name> com.sun.faces.numberOfViewsInSession</param-name>
<param-value>15</param-value>
</context-param>
Consulte también las preguntas frecuentes de Mojarra para conocer otros parámetros específicos de Mojarra y esta respuesta relacionada com.sun.faces.numberOfViewsInSession vs com.sun.faces.numberOfLogicalViews
A medida que un usuario que ha iniciado sesión en la aplicación navega por las páginas, ¿se seguirá acumulando el estado de los componentes en el servidor?
Técnicamente, eso depende de la implementación. Si está hablando de navegación de página a página (solo solicitudes GET), Mojarra no guardará nada en la sesión. Sin embargo, si son solicitudes POST (formularios con enlaces de comando/botones), Mojarra guardará el estado de cada formulario en la sesión hasta el límite máximo. Esto permite al usuario final abrir varios formularios en diferentes pestañas del navegador en la misma sesión.
O, cuando el ahorro de estado se establece en cliente, JSF no almacenará nada en la sesión. Puede hacerlo mediante el siguiente parámetro de contexto en web.xml
:
<context-param>
<param-name>javax.faces.STATE_SAVING_METHOD</param-name>
<param-value>client</param-value>
</context-param>
Luego se serializará en una cadena cifrada en un campo de entrada oculto con el nombre javax.faces.ViewState
del formulario.
No entiendo cuál es el beneficio de mantener el estado del componente de la interfaz de usuario en el lado del servidor. ¿No es suficiente pasar directamente los datos validados/convertidos a beans administrados? ¿Puedo/debo intentar evitarlo?
Eso no es suficiente para garantizar la integridad y solidez de JSF. JSF es un marco dinámico con un único punto de entrada de control. Sin una gestión de estado, uno podría falsificar/piratear solicitudes HTTP de cierta manera (por ejemplo disabled
, manipulando readonly
y rendered
atributos), para permitir que JSF haga cosas diferentes (y potencialmente peligrosas). Incluso sería propenso a ataques CSRF y phishing.
¿Y eso no consumirá demasiada memoria en el lado del servidor si hay miles de sesiones de usuarios simultáneas? Tengo una aplicación donde los usuarios pueden publicar blogs sobre ciertos temas. Estos blogs son bastante grandes. Cuando haya una publicación o una solicitud para ver los blogs, los blogs grandes se guardarán como parte del estado de los componentes. Esto consumiría demasiada memoria. ¿No es esto una preocupación?
La memoria es particularmente barata. Simplemente dale al servidor de aplicaciones suficiente memoria. O si el ancho de banda de la red le resulta más económico, simplemente cambie el ahorro de estado al lado del cliente. Para encontrar la mejor coincidencia, simplemente realice una prueba de esfuerzo y perfile su aplicación web con la cantidad máxima esperada de usuarios simultáneos y luego proporcione al servidor de aplicaciones entre el 125% y el 150% de la memoria máxima medida.
Tenga en cuenta que JSF 2.0 ha mejorado mucho en la gestión del estado. Es posible guardar un estado parcial (por ejemplo, solo se <h:form>
guardará el estado en lugar de todo desde <html>
el principio hasta el final). Mojarra por ejemplo hace eso. Un formulario promedio con 10 campos de entrada (cada uno con una etiqueta y un mensaje) y 2 botones no ocuparía más de 1 KB. Con 15 vistas en una sesión, eso no debería ser más de 15 KB por sesión. Con ~1000 sesiones de usuarios simultáneas, eso no debería ser más de 15 MB.
Su preocupación debería centrarse más en los objetos reales (beans administrados y/o incluso entidades de base de datos) en el alcance de la sesión o de la aplicación. He visto muchos códigos y proyectos que duplican innecesariamente toda la tabla de la base de datos en la memoria de Java en forma de un bean con ámbito de sesión donde se usa Java en lugar de SQL para filtrar/agrupar/organizar los registros. Con ~1000 registros, eso superaría fácilmente los 10 MB por sesión de usuario . Además, cuando binding
se usa en un bean con alcance de vista o sesión, básicamente estás manteniendo innecesariamente una copia profunda de todo el árbol de componentes JSF en la memoria del servidor.
Ver también:
- ¿JSF evita llamadas a acciones de beans administrados no renderizados mediante solicitudes manipuladas?
- JSF sin @ViewScoped
- ¿Cuál es el tiempo de construcción de la vista?
- ¿Cómo funciona el atributo 'vinculante' en JSF? ¿Cuándo y cómo se debe utilizar?