EJB 环境下的 singleton ?

02-11-29 jackyz
我应用的结构是这样的:

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


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

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

private static Map cache = new Hashtable();
<p class="indent">

似乎并不管用,而且,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;
  }

}
<p class="indent">

似乎也不管用,或者因为它也是由 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;
}
<p class="indent">


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


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

jackyz
2002-12-03 14:03
请了解这个问题的朋友不吝赐教。

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

why10k
2002-12-03 17:51
我的实现是在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一次而已.

jackyz
2002-12-03 19:23
to: banq

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

to: why10k

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

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

banq
2002-12-04 09:39
目前比较好的解决方案是
http://www.tangosol.com/coherence.jsp

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

banq
2002-12-04 09:49
If you're just trying to cache non-transactional data, Read-Only entity
beans and our JSP cache tags are a good choice.

jackyz
2002-12-04 12:47
thanks. very appreciate.