2013-03-13 4 views
3

Мой проект использует JSF2.0 и CDI. Для одной страницы я хочу, чтобы мой поддерживающий компонент соответствовал продолжительности жизни страницы. @ViewScoped кажется идеально подходящим, но он не является частью CDI, а затем делает наше решение несовместимым. Тогда моим следующим вариантом будет CDI @ConversationScoped. Кажется, единственный способ отметить границу разговора - это программный путь через chat.begin и chat.end (я использовал Seam 2.x, там вы можете использовать аннотации для отметки границы разговора). Моя страница сидит в общем макете с глобальной навигацией, что означает, что есть «неограниченные» способы оставить мою страницу. Как я могу убедиться, что разговор завершен в зависимости от того, какой пользователь может выбрать (например, нажав на глобальную навигационную опцию, которая полностью находится за пределами моего бэк-контроля)? И я надеюсь, что решение не распространит код на другие модули; и если это неизбежно, я надеюсь, что это может быть реализовано сквозным образом (АОП).Как очистить CDI @ConversationScoped

ответ

4

Этого можно достичь с помощью заказа ConfigurableNavigationHandler.

  1. Реализация 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. Зарегистрируйте свой собственный навигационный обработчик в лица-config.xml

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

Этот подход является централизованной и минимально инвазивной

+0

Это работает. Благодаря! – chaoshangfei

+0

@FangZhang вас очень приветствует – kolossus

+0

Это уродливое обходное решение. Вместо этого я бы использовал CODI-Conversations. –

0

Как я знаю - вы не можете. Практически невозможно (трудно) определить, была ли ссылка открыта на текущей или новой вкладке (для нового вам нужно оставить активную беседу) в JSF.

Но хорошие новости - разговор будет закрыт автоматически через 10 минут бездействия (по умолчанию).

+0

Ну, оставляя проблему дизайна в стороне. Технически вы можете сделать все навигационные запросы через объект службы навигации. И каждый разговор имеет идентификатор. После того, как целевая страница будет открыта, мы сможем сохранить идентификатор в объекте службы, если какой-либо следующий запрос навигации не предназначен для целевой страницы, тогда мы знаем, что нам нужно завершить разговор. Поскольку CDI несколько основан на Seam, я надеялся, что у меня будет более элегантное решение. – chaoshangfei

+0

Обработчик окон на стороне клиента из CODI может правильно определить новую вкладку/окно. –

Смежные вопросы