sessionscoped sessionscope jsf-2 cdi

jsf-2 - sessionscope - jsf session



Cómo finalizar de forma limpia un CDI @ConversationScoped (2)

Como sé, no puedes. Es casi imposible (difícil) determinar si el enlace se abrió en la pestaña actual o nueva (para lo nuevo debe dejar la conversación activa) en JSF.

Pero buenas noticias: la conversación se cerrará automáticamente después de 10 minutos de inactividad (por defecto).

Mi proyecto usa JSF2.0 y CDI. Para una página, quiero que mi bean de respaldo coincida con la vida útil de la página. @ViewScoped parece un ajuste perfecto pero no es parte de CDI y luego hace que nuestra solución no sea consistente. Entonces mi siguiente opción sería CDI @ConversationScoped. Me parece que la única manera de marcar el límite de una conversación es mediante el modo de programa a través de conversation.begin y conversation.end (he usado Seam 2.x, allí puede usar anotaciones para marcar el límite de la conversación). Mi página está en un diseño común con navegación global, lo que significa que hay formas "ilimitadas" de abandonar mi página. ¿Cómo puedo asegurarme de que la conversación finalice de la forma que el usuario elija (por ejemplo, hacer clic en una opción de navegación global que esté totalmente fuera del control de mi bean de respaldo)? Y espero que la solución no extienda el código a otros módulos; y si eso es inevitable, espero que pueda implementarse de manera transversal (AOP).


Esto se puede lograr con un ConfigurableNavigationHandler personalizado.

  1. Implementar un JSF NavigationHandler

    public class NavigationHandlerTest extends ConfigurableNavigationHandler { private NavigationHandlerTest concreteHandler; public NavigationHandlerTest(NavigationHandler concreteHandler) { this.concreteHandler = concreteHandler; } @Override public void handleNavigation(FacesContext context, String fromAction, String outcome) { //here, check where navigation is coming from and based on that, retrieve the CDI bean and kill the conversation if(fromAction.equals("someAction"){ BeanManager theBeanManager = getBeanManager(context); Bean bean = theBeanManager.getBeans("yourCDIBean").iterator().next() CreationalContext ctx = theBeanManager.createCreationalContext(bean); MyBeanType o = theBeanManager.getReference(bean, bean.getClass(), ctx); //retrieve the bean from the manager by name. You''re guaranteed to retrieve only one of the same name; o.getConversation.end(); //end the conversation from the bean reference } //proceed with normal navigation concreteHandler.handleNavigation(context, fromAction, outcome); } //This method provides access to the cdi bean manager. You need it to be able to //gain access to the cdi bean and from that to the injected conversation instance public BeanManager getBeanManager(FacesContext facesContext){ BeanManager cdiBeanManager = (BeanManager)((ServletContext) facesContext.getExternalContext().getContext()).getAttribute("javax.enterprise.inject.spi.BeanManager"); return cdiBeanManager; } }

  2. Registre su controlador de navegación personalizado en faces-config.xml

    <application> <navigation-handler>com.foo.bar.NavigationHandlerTest</navigation-handler> </application>

Este enfoque es centralizado y mínimamente invasivo