Possible to inject same stateful session bean instance into multiple other session beans?
Is it possible to make the container inject the same stateful session bean instance into multiple other stateful session beans?
Given the following classes:
@Stateful
public class StatefulTwoBean implements StatefulTwo {
@EJB
private StatefulOne statefulOne;
}
@Stateful
public class StatefulThreeBean implements StatefulThree {
@EJB
private StatefulOne statefulOne;
}
In the above example, StatefulTwoBean and StatefulTh开发者_JS百科reeBean each get injected their own instance of StatefulOneBean.
Is it possible to make the container inject the same instance of StatefulOneBean into both StatefulTwoBean and StatefulThreeBean?
The problem is this - Stateful beans' isntances are allocated by differentiating the clients that call them. Glassfish (and perhaps others) don't propagate this difference on injected beans. The EJB specification, as far as I remember, isn't clear about this.
So your solution is to implement the differentiation yourself. How to achieve this. I'm not pretending this is the most beautiful solution, but it worked. - we did it by putting a Facade (an EJB itself) (I'm calling it a facade, although it does not entirely cover the facade pattern) in front of all our EJBs, with the following code:
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);
.....
}
The important parameter is sessionId
- this is something both the client and the server know about, and identifies the current seesion between them.
On the client we used a dynamic proxy to call this facade. So the calls look like this:
getBean(MyConcreteEJB.class).someMethod()
, an the getBean method created the proxy, so that callers didn't have to know about the facade bean.
The SessionRegistry
had
private static ThreadLocal<SessionContext> localSessionContext = new
ThreadLocal<SessionContext>();
And the SessionContext
was simply a Map providing set(key, value)
and get(key)
So now, instead of using @Stateful
beans to store your state, you could use the SessionContext
.
In EJB3.1 you can create your StatefulOne
bean as singleton (using the @Singleton
annotation) giving you the desired semantics. JBoss should already support this annotation (they've wrote the standard).
精彩评论