2013-10-01 27 views
5

Czy jest możliwe ustawienie limitu czasu konwersacji dla wszystkich obiektów konwersacji wprowadzonych do @Named?Ustawianie limitu czasu rozmów CDI na świecie

Mam kilka @ConversationScoped fasolę, np .:

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(); 
     } 
    } 
}   

Domyślny limit czasu dla tych rozmów jest 600000 ms. Chcę wiedzieć, czy jest jakiś sposób ustawić limity czasu rozmów globalnie czy muszę ustawić go w każdej fasoli przez

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

(problemem jest to, że istnieje wiele CDI fasoli i ustawienie limitu czasu ręcznie w każdej z nich nie jest najlepszym rozwiązaniem)

+0

jak niektóre odpowiedzi poniżej wykazały, tam nieprawdaż jest to standardowy sposób robienia tego. Wszystko, co robisz (nie licząc odpowiedzi Stasala), nie będzie przenośne. – LightGuard

Odpowiedz

2

Więc tutaj jest rozwiązanie użyłem (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) {} 
} 

Kontekst jest wprowadzany do odbiornika, a limit czasu jest ustawiany, gdy użytkownik uruchamia sesję.

+0

Kiedy wywoływana jest sesjaCreated? Czy ta klasa powinna być skonfigurowana w web.xml? – Emerald214

+0

Metoda sessionCreated jest wywoływana podczas tworzenia nowej sesji klienta. Ta klasa powinna być skonfigurowana w deskryptorze web.xml lub opisana jak w powyższym przykładzie kodu (ale atrybut "metadata-kompletny" w pliku web.xml powinien zostać pominięty lub równy "false"). Więcej informacji na temat zdarzeń lifletowych serwletów hadlingowych znajduje się tutaj: http://docs.oracle.com/javaee/7/tutorial/servlets002.htm#BNAFJ – stasal

2

ze szwem/Weld powinien być w stanie coś zrobić jak poniżej:

@Inject 
private HttpConversationContext conversationContext; 

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

przeciwnym razie wierzę, trzeba będzie ustawić ją na każdej rozmowie.

EDIT: Uwaga użyłem zdarzenia niestandardowego, to samo można osiągnąć z:

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

Dzięki za podpowiedź, zaimplementowana w ten sam sposób, opublikujesz rozwiązanie teraz :) – stasal

+0

Co to jest "PreloadCompleteEvent"? Nie można znaleźć nic na ten temat w dokumentacji (Weld 2.x). Tak więc używam podobnej metody obserwatora: 'public void observeAppInit (@Observes @Initialized (ApplicationScoped.class) Zdarzenie Object)' i wykonaj pracę wewnątrz tej metody, która działa zgodnie z sugestią. –

+0

PreloadCompleteEvent jest zdarzeniem niestandardowym, aby użyć wartości domyślnej, można również użyć polecenia 'public void observePreload (@Observes @Started WebApplication webapp) {' lub co zasugerowałeś –

1

Można to łatwo zrobić w sposób przenośny za pomocą 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 
    } 

} 

Inną przenośną opcją jest dekorowanie rozmowy. (Uwaga: niesprawdzone.)

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

Powinieneś wymienić import, by lepiej go zrozumieć. javax.enterprise.context.Zainicjowany jest częścią java-ee-api 7, ale my na przykład używamy java-ee 6, więc jedynym sposobem jest poleganie na cdi-api jboss, który jest bardziej przenośny niż moje rozwiązanie, ale wciąż nie jest w 100% – stasal

+0

@stasal, tak, CDI 1.1 jest w tym przypadku wymagane. Poprawiłem moją odpowiedź. –

0

Można również zsynchronizować czas oczekiwania na rozmowę fasoli z limitu czasu sesji bieżącej żądanie http:

if (conversation.isTransient()) { 
     conversation.setTimeout(((HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext() 
       .getRequest()).getSession().getMaxInactiveInterval()*1000); 
     conversation.begin(); 
    }