EJB 环境下的 singleton ?

我应用的结构是这样的:


client
|
----- 网络边界 -----
|
+--> sessionfacade(sessionbean)(stateful)(remote)
|
+--> util(sessionbean)(stateless)(local)
|
+--> entity(entitybean)(local){CMP/CMR}

在 util 层次上,我采用 stateless sessionbean 来服务多个 sessionfacade 会话用到的通用功能。为提高性能,我要在这个层次提供 cache 能力,比方,缓存部分查询结果,我的办法是存一个 MAP 实例进行全局 cache。显然,这个缓存功能的入口应该是在多个 util 的实例之间共享的,也就是说,应该是一个 singleton 对象。但,我似乎无法在 EJB 环境下实现它。至少在我搭建的 apusic 测试环境中是这样。我尝试过这样几种方法:

1.static 成员变量
示例代码:


private static Map cache = new Hashtable();

似乎并不管用,而且,EJB的编程限制中提到因该避免使用非 final 的 static 变量(既使加了 final 还是会再第二个会话中丢失)。

2.标准的 singleton 模式
示例代码:


public class Singleton {

private Singleton() {}

// singleton logic
private static Singleton singleton;
public static Singleton getInstance(){
if(singleton == null) singleton = new Singleton();
return instance;
}

}

似乎也不管用,或者因为它也是由 static 的一个对象实现的,或许在多 classloader 的环境下,就会失去唯一性。

3.在系统 JNDI 中保存公用对象


private Map getCache() {
Map cache = null;
try {
cache = (Map) jndiUtil.get(classname + ".cache");
if (cache == null) {
cache = new Hashtable();
jndiUtil.set(classname +
".cache", cache);
}
} catch (Exception e) {
log.debug(
"AuthManagerBean.init()" , e );
}
log.debug(
"cache:" + cache );
return cache;
}

这是某篇文章中推荐的方法,但,似乎也不管用(或许我的方法不对?)给我的感觉是在 session facade 的一个会话退出之后,这个 stateless sessionbean (以及它所创建的JNDI context)也被连带的 renew 了。


有那位大侠曾经在应用中碰见过类似的场景?请不吝指教解决方法,解我于倒悬。(如能给出示例代码,更将不胜感激)

请了解这个问题的朋友不吝赐教。

不要着急,我也在解决这个问题,等我看完你的代码再和你研究,我目前主要研究在cluster下的EJB singleton问题,因为单个EJB可以容易解决Singleton,但是多个麻烦,我查阅资料,一般说尽量回避这个问题,因为EJB是分布式多容器的,比较好的解决办法是stateless session +数据库

我的实现是在SESSION BEAN 里调用辅助类,在辅助类里实现单件,没问题.
public class Example{
public static Example getInstance(){
if(me==null)
me=new Example();
return me;
}
private Example(){
....
}
private static Example me=null;
}
ejb环境下应该在单机实现吧,如果辅助类与状态无关,CLUSTER也没关系,无非多NEW一次而已.

to: banq

我的项目中已经修改原先设计,设法“回避”了这个问题。(可以考虑 client side 的 singleton 或将会话相关信息缓存在外层 sessionbean 中以解决性能问题)但我觉得,这仍然不失为一个值得研究的问题。希望能和大家一起探讨。

to: why10k

你可以留意我贴出的方法2的代码,与你的辅助类的做法是一致的,或许我们用的 container 不同(我的测试在国产的 apusic 2 下运行)。我得到的结果是此时 singleton 已经失效。这至少说明这种“标准的 singleton 方式”在某些 appserver 下可能已经不再可靠了。

谢谢热心参与探讨的朋友。

目前比较好的解决方案是
http://www.tangosol.com/coherence.jsp

Jive 2.5 用这个方案 这是cluster下的cache

If you're just trying to cache non-transactional data, Read-Only entity
beans and our JSP cache tags are a good choice.

thanks. very appreciate.