GlassFish在不同的物理服务器上运行EJB

时间:2012-02-25 18:13:49

标签: java-ee glassfish ejb jms jndi

我在GlassFish 3.1上运行了一个Java EE 6 Web应用程序。该应用程序使用本地Singleton EJB MySingleton的2个实例。 MySingleton的每个实例都通过API连接到第三方软件。

MySingleton.java

@Singleton
@LocalBean
public class MySingleton { 
    @PersistenceContext private EntityManager em;    
    private ThirdPartyAPI thirdPartyAPI;
    ...
}

MySingletonManager.java

@Singleton
@LocalBean
public class MySingletonManager { 
    @EJB private MySingleton mySingletonA;
    @EJB private MySingleton mySingletonB;        ///Aargh! They can't run on the same server!!
    ...
}

以下是限制因素:

  1. 第三方软件提供商要求其软件在不同的物理服务器上运行ThirdPartyAPI的每个实例
  2. MySingleton使用EntityManager的注入实例,该实例是同一PersistenceContext上的查询和交易所必需的。
  3. 为了满足约束1,我认为我需要远程访问Singleton EJB:我需要告诉应用服务器类似“在服务器A上运行mySingletonA,在服务器B上运行mySingletonB”。为此,我看到可以通过JNDI调用远程EJB。

    为了满足约束2,我认为我需要使用GlassFish clustering,因为需要在MySingleton的2个实例之间共享PersitenceContext。

    不幸的是,我无法找到关于如何一起使用2个技术的任何参考资料(远程EJB和集群)。

    我正在寻找有关此方案的首选架构的提示或建议,以及最终的一些实施指南。

1 个答案:

答案 0 :(得分:2)

一些事情......

首先,如果您要连接到外部EIS系统,“正确”的方法是编写JCA适配器并使用@Resource注入实例。他们写起来相当简单,Adam Bien有一个编写简单例子的好例子。想想@Resource就像为您的应用程序制作自定义数据源一样。一旦你弄明白了,这真的很有趣。从技术上讲,JEE6规范不支持编写任何使用套接字或同步的EJB。

如果执行此操作,则可以在群集的两个成员上安装此适配器。每个集群成员都可以指向第三方软件的外部实例。如果任何一个集群成员发生故障,一切都将继续只运行。

但是......如果你真的想用单身EJB做一些艰难的事情,你可能会这样做:

首先,摆脱MySingletonManager。群集是透明的,你不应该知道你是群集的。第二次将您的单身代码更改为:

@Singleton
@Remote
public class MySingleton { 
    @PersistenceContext private EntityManager em;    
    private ThirdPartyAPI thirdPartyAPI;
    ...

}

了解Singleton CAN NOT 具有状态非常重要。如果ThirdPartyAPI在调用之间保持状态,则会发生有趣的事情。您还必须在thirdPartyAPI周围放置一个循环连接代码装饰器,以便它将连接到您的两个ThirdPartyServers。最后,创建一个GlassFish集群并在整个集群中部署EJB。像这样将它注入你的代码:

@EJB MySingleton myIns;

这将自动在群集中的某个位置找到EJB,并为您提供一个句柄。现在,假设这一切都有效,我没有错过任何东西,你现在有一个并发问题,因为默认情况下,对任何EJB的访问都是序列化的。你可以添加@ConcurrencyAttribute(NO_LOCK),但EntityManager不是线程安全的,它也是事务性的。

总的来说,Singleton EJB会给你带来很多问题。花时间写一个JCA适配器!