2009-12-10 114 views
1

是否有可能讓容器將相同的有狀態會話bean實例注入多個其他有狀態會話Bean?可能將相同的有狀態會話bean實例注入到多個其他會話bean中?

考慮以下類:

@Stateful 
public class StatefulTwoBean implements StatefulTwo { 

    @EJB 
    private StatefulOne statefulOne; 

} 

@Stateful 
public class StatefulThreeBean implements StatefulThree { 

    @EJB 
    private StatefulOne statefulOne; 

} 

在上面的例子中,StatefulTwoBeanStatefulThreeBean分別獲得注入的StatefulOneBean自己的實例。

是否有可能使容器注入相同的實例StatefulOneBean到StatefulTwoBean和StatefulThreeBean

+0

什麼是您的應用程序服務器。 – Bozho 2009-12-10 15:16:27

+0

@Bozho爲什麼要麻煩? – 2009-12-10 16:14:00

+2

@Pascal,好吧,我曾經研究過一個類似的問題,並發現WebLogic(如果我記得沒錯的話)有一些實現他想要的功能。那時我正在使用Glassfish(不能)。因此,如果他的應用程序服務器是glassfish,我可以查看代碼庫並找到適合他的問題:) – Bozho 2009-12-10 16:27:05

回答

2

問題是這樣的 - 有狀態bean的isntances是通過區分調用它們的客戶端來分配的。 Glassfish(也許還有其他人)不會在注入的豆類中傳播這種差異。據我所知,EJB規範並不清楚這一點。

所以你的解決方案是自己實現差異化。如何實現這一點。我不假裝這是最美麗的解決方案,但它的工作。

public Object call(Object bean, 
     String methodName, 
     Object[] args, 
     Class[] parameterTypes, 
     UUID sessionId) throws Throwable { 

    //find the session 
    SessionContext sessionContext = SessionRegistry.getSession(sessionId); 
    //set it as current 
    SessionRegistry.setLocalSession(sessionContext); 
    ..... 
} 
: - 我們通過把一個門面(一個EJB本身)(我稱它是門面,雖然它不完全覆蓋門面模式)在我們所有的EJB的前面,用下面的代碼做了

重要的參數是sessionId - 這是客戶端和服務器都知道的事情,並確定它們之間的當前見解。

在客戶端,我們使用動態代理來調用這個門面。所以調用如下所示: getBean(MyConcreteEJB.class).someMethod(),getBean方法創建代理,以便調用者不必知道門面bean。

SessionRegistry

private static ThreadLocal<SessionContext> localSessionContext = new 
    ThreadLocal<SessionContext>(); 

而且SessionContext只是所以現在提供set(key, value)get(key)

一個地圖,而不是使用@Stateful豆來存儲你的狀態,你可以使用SessionContext

2

在EJB3.1中,您可以創建您的StatefulOne bean作爲單例(使用@Singleton註釋),爲您提供所需的語義。 JBoss應該已經支持這個註釋(他們已經寫了標準)。

+0

這個單身人士有那麼多的範圍?應用程序廣泛還是像有狀態bean那樣綁定到客戶端? – Sylar 2009-12-11 07:26:11

+1

@Sebastian:單例bean被定義爲具有廣泛的應用範圍。對於會話範圍,就像您已經提到的那樣,您必須改用會話bean。 – jawi 2009-12-11 07:56:14