How to Completely Complete CDI @ConversationScoped

My project uses JSF2.0 and CDI. For one page, I want my bean support to match the page life span. @ViewScoped looks perfect, but it is not part of the CDI, and then makes our solution consistent. Then my next option would be CDI @ConversationScoped. It seems the only way to mark the border of the conversation is through the program path through chat.begin and chat.end (I used Seam 2.x, there you can use annotations to mark the border of the conversation). My page sits in a general layout with global navigation, which means there are "unlimited" ways to leave my page. How can I make sure that the conversation is completed depending on which user can choose (for example, by clicking on the global navigation option, which is completely out of my control of the bean)? And I hope that the solution does not extend the code to other modules; and if this is inevitable, I hope that this can be implemented in a cross-cutting manner (AOP).

+3
source share
2 answers

This can be achieved using a custom ConfigurableNavigationHandler .

  • Implement 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; } } 
  • Register your own navigation handler in faces-config.xml

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

This approach is centralized and minimally invasive.

+4
source

As I know, you cannot. It is almost impossible (difficult) to determine whether the link was opened on the current or new tab (for the new you need to leave the active dialog) in JSF.

But the good news is that the conversation will be closed automatically after 10 minutes of inactivity (by default).

0
source

All Articles