2013-10-01 2 views
5

Возможно ли установить тайм-аут разговора по всему миру для всех объектов беседы, введенных в @Named beans?Настройка тайм-аута тайм-аута CDI глобально

У меня есть несколько @ConversationScoped бобы, например .:

import javax.annotation.PostConstruct; 
import javax.enterprise.context.Conversation; 
import javax.enterprise.context.ConversationScoped; 
import javax.inject.Inject; 
import javax.inject.Named; 

@Named 
@ConversationScoped 
public class SomeBean1 { 

    @Inject 
    private Conversation conversation; 

    @PostConstruct 
    private void init() { 
     if (conversation.isTransient()) { 
      conversation.begin(); 
     } 
    } 
} 

@Named 
@ConversationScoped 
public class SomeBean2 { 

    @Inject 
    private Conversation conversation; 

    @PostConstruct 
    private void init() { 
     if (conversation.isTransient()) { 
      conversation.begin(); 
     } 
    } 
}   

тайм-аут по умолчанию для этих разговоров 600000 мс. Я хочу знать, есть ли способ, чтобы установить время ожидания переговоров по всему миру, или мне нужно, чтобы установить его в каждом компоненте по

if (!conversation.isTrainsient()) { 
    conversation.setTimeout(MY_CUSTOM_TIMEOUT); 
} 

(проблема в том, что есть много CDI фасолью и настройки тайм-аута вручную в каждом из них не является лучшим решением)

+0

Как некоторые ответы ниже продемонстрировали, там ISN Это стандартный способ сделать это. Все, что вы делаете (за исключением ответа стазала), не будет переносимым. – LightGuard

ответ

2

Итак, вот решение, которое я использовал (Oracle WebLogic 12c, WELD 1.1.Final):

import org.jboss.weld.context.http.HttpConversationContext; 

import javax.inject.Inject; 
import javax.servlet.annotation.WebListener; 
import javax.servlet.http.HttpSessionEvent; 
import javax.servlet.http.HttpSessionListener; 

@WebListener 
public class SessionListener implements HttpSessionListener { 

    @Inject 
    private HttpConversationContext conversationContext; 

    @Override 
    public void sessionCreated(HttpSessionEvent httpSessionEvent) { 
     if (conversationContext != null) { 
      final long DEFAULT_TIMEOUT = 2 * 60 * 60 * 1000; 
      if (conversationContext.getDefaultTimeout() < DEFAULT_TIMEOUT){ 
       conversationContext.setDefaultTimeout(DEFAULT_TIMEOUT); 
      } 
     } 
    } 

    @Override 
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {} 
} 

Контекст вводится в слушатель, а таймаут устанавливается, когда пользователь запускает сеанс.

+0

Когда вызов sessionCreated называется? Должен ли этот класс настраиваться в web.xml? – Emerald214

+0

Метод sessionCreated вызывается при создании нового клиентского сеанса. Этот класс должен быть либо сконфигурирован в дескрипторе web.xml, либо аннотирован как в приведенном выше примере кода (но атрибут «metadata-complete» в web.xml должен быть опущен или равен «false»). Подробнее о событиях жизненного цикла сервлетов оиллинга написано здесь: http://docs.oracle.com/javaee/7/tutorial/servlets002.htm#BNAFJ – stasal

2

с Seam/Weld вы должны быть в состоянии сделать что-то вроде следующего:

@Inject 
private HttpConversationContext conversationContext; 

public void observePreload(@Observes PreloadCompleteEvent event) { 
    //Set global conversation timout to 60000 ms 
    conversationContext.setDefaultTimeout(60000); 
} 

в противном случае я считаю, вы должны установить его для каждого разговора.

EDIT: Обратите внимание, я использовал пользовательское событие, то же самое может быть достигнуто с:

public void observePreload(@Observes @Started WebApplication webapp) { 
+0

Спасибо за ваш намек, реализовано так же, опубликует решение сейчас :) – stasal

+0

Что такое 'PreloadCompleteEvent'? Не удалось найти что-либо в документации (Weld 2.x). Таким образом, я использую аналогичный метод наблюдателя: 'public void observAppInit (событие @Observes @Initialized (ApplicationScoped.class) объекта)' и выполнять работу внутри этого метода, которая работает как предлагается. –

+0

PreloadCompleteEvent - это настраиваемое событие, для использования по умолчанию вы также можете использовать public void observPreload (@Observes @Started WebApplication webapp) {'или что вы предложили –

1

Это легко можно сделать переносным способом с CDI 1.1.

import javax.enterprise.context.Conversation; 
import javax.enterprise.context.ConversationScoped; 
import javax.enterprise.context.Initialized; 
import javax.enterprise.event.Observes; 
import javax.inject.Inject; 
import javax.servlet.ServletRequest; 

public class ConversationTimeoutDefaultSetter { 

    @Inject 
    private Conversation conversation; 

    public void conversationInitialized(
      @Observes @Initialized(ConversationScoped.class) 
      ServletRequest payload) { 
     conversation.setTimeout(1800000L); // 30 minutes 
    } 

} 

Другой переносной вариант - украсить беседу. (Внимание: не тестировалась.)

import static javax.interceptor.Interceptor.Priority.APPLICATION; 

import javax.annotation.Priority; 
import javax.decorator.Decorator; 
import javax.decorator.Delegate; 
import javax.enterprise.context.Conversation; 
import javax.inject.Inject; 

@Decorator 
@Priority(APPLICATION) 
public class ConversationTimeoutDefaultSetter implements Conversation, Serializable { 

    private static final long serialVersionUID = 1L; 

    @Inject 
    @Delegate 
    private Conversation delegate; 

    private void setDefaultTimeout() { 
     delegate.setTimeout(1800000L); // 30 minutes 
    } 

    @Override 
    public void begin() { 
     setDefaultTimeout(); 
     delegate.begin(); 
    } 

    @Override 
    public void begin(String id) { 
     setDefaultTimeout(); 
     delegate.begin(id); 
    } 

    @Override 
    public void end() { 
     delegate.end(); 
    } 

    @Override 
    public String getId() { 
     return delegate.getId(); 
    } 

    @Override 
    public long getTimeout() { 
     return delegate.getTimeout(); 
    } 

    @Override 
    public void setTimeout(long milliseconds) { 
     delegate.setTimeout(milliseconds); 
    } 

    @Override 
    public boolean isTransient() { 
     return delegate.isTransient(); 
    } 

} 
+0

Вы должны были указать импорт для лучшего понимания, я думаю. javax.enterprise.context.Инициализированный является частью java-ee-api 7, но мы, например, используем java-ee 6, поэтому единственный способ зависит от jboss cdi-api, который более переносим, ​​чем мое решение, но все же не на 100%. – stasal

+0

@stasal, да, для этого требуется CDI 1.1. Я исправил свой ответ. –

0

Вы также можете синхронизировать время ожидания вашего разговора боба с тайм-аута сеанса вашего текущего запроса HTTP:

if (conversation.isTransient()) { 
     conversation.setTimeout(((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext() 
       .getRequest()).getSession().getMaxInactiveInterval()*1000); 
     conversation.begin(); 
    } 
Смежные вопросы