2011-07-17 20 views
8

Tengo un método en una vista de Bean con ámbito con la anotación @PreDestroy y otro con la anotación @PostConstruct.El método JSF 2.1 ViewScopedBean @PreDestroy no se llama

El método @PostConstruct se llama correctamente cada vez que navego a la página que utiliza esta vista de bean con ámbito.

Sin embargo, cuando navego a una página nueva (que no utiliza este Bean de ámbito de vista) por <h:link/>, nunca se llama al método @PreDestroy.

No estoy hablando de changing manually the url or the end of the session, solo de una caja de navegación.

¿Qué me falta?

Gracias de antemano

Respuesta

15

Esto es por diseño. Solo se destruirá inmediatamente cuando una acción POST genere una navegación que no sea una devolución de datos a la misma vista (es decir, el método de acción no devolvió null o void, sino un String completo, incluso cuando esté vacío).

El <h:link> genera un enlace GET que no invoca ninguna acción POST. Como no es confiablemente posible notificar al lado del servidor mediante una solicitud HTTP (XML) cuando la vista está descargada, no se puede notificar a JSF que destruya el bean con ámbito de vista asociado con la vista. En tal caso, el bean con ámbito de vista solo se destruirá cuando expire la sesión o cuando se hayan superado las vistas lógicas máximas en sesión (el valor predeterminado es 15) y la vista asociada es la primera en orden.

Si realmente quiere estropear la vista con ámbito de frijol por una acción navigaiton, entonces su mejor apuesta es hacer una petición POST por <h:commandLink> lugar y una redirección devolviendo el resultado de navegación con ?faces-redirect=true parámetro. Pero después de todo esto no es amigable con los motores de búsqueda, ya que los bots no indexarán los enlaces POST.

No me gustaría que la vista siga estando en la sesión. Si tiene la intención de hacer algo de limpieza o registro, buscaría formas alternativas, dependiendo del requisito funcional concreto.

En teoría sería posible por HTML DOM onbeforeunload evento, pero este es un evento no estándar y el comportamiento del navegador es indeterminado en cuanto a lo que sucede cuando se envía una petición AJAX durante ese evento. A veces llegará, pero a veces tampoco. Actualización: en práctica, esto se ha implementado en OmniFaces @ViewScoped desde OmniFaces 2.2 con la ayuda de synchronous XHR y está funcionando bastante bien en los principales navegadores. Desde la versión 2.3, incluso destruye físicamente el estado de la vista lateral del servidor JSF asociado.

+0

Una pequeña corrección está en orden. Incluso si realiza un redireccionamiento, si lo redirecciona a la misma vista desde donde se originó la solicitud POST, JSF no destruirá el bean con ámbito de vista. Para que se destruya una vista del bean con ámbito, deberá renderizar una vista diferente por completo después de procesar la solicitud POST. – RajV

2

He preparado un pequeño proyecto de NetBeans que demuestra cuándo JSF2.2 CDI-compatible @ViewScoped beans (javax.faces.view.ViewScoped) se libera para la recolección de basura en diferentes casos de navegación (para Mojarra 2.2.9, Glassfish4, NetBeans8 .0.2, JDK1.7), disponible para download here. El código se omite aquí, por favor ver esa descarga.

Los casos de navegación manipulados y los resultados se resumen en esta imagen:

Image showing index page using @ViewSCoped bean with JSF navigation cases to a done landing page

Para supervisar los granos @ViewScoped, utilice VisualVM contra Glassfish (o el NetBeans Profiler incorporado en el mini proyecto) y filtre la vista de clase del histograma del montón Hempler memory en el nombre del paquete 'webel.com.jsf'. La siguiente imagen muestra 66 instancias absurdas de webel.com.jsf.Jsf22ViewBean después de una copiosa experimentación con h: link, GET de URL del navegador y GET de RELOAD del navegador, cuyas instancias no serán basura (que puede probar usando VisualVM Perform botón GC):

enter image description here

en comparación, navegar fuera de la index.xhtml (que utiliza el grano @ViewScoped una vez para una variable simple eL leer) a done.xhtml (que no utiliza el grano en todo) usando h: commandButton y una expresión de método de acción o una cadena de acción da como resultado que se abra el beans @ViewScoped para la recolección de basura (siempre hay una referencia del WeldClientProxy a un bean @ViewScoped, y mientras navegas hacia atrás y adelante usando h: commandButton WeldClientProxy se mueve de un bean liberable al siguiente).

+0

Lo anterior responde a la pregunta (se basa en la respuesta de BalusC) al demostrar exhaustivamente los diversos casos de navegación, pero no explica qué hacer con los beans @ViewScoped resultantes "colgantes" que no recogerán basura: lo pido como una pregunta aquí: http://stackoverflow.com/questions/30410601/jsf2-2-how-detect-and-remove-unused-viewscoped-beans-that-cant-be-garbage-col –

Cuestiones relacionadas