我在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!!
...
}
以下是限制因素:
ThirdPartyAPI
的每个实例EntityManager
的注入实例,该实例是同一PersistenceContext
上的查询和交易所必需的。为了满足约束1,我认为我需要远程访问Singleton EJB:我需要告诉应用服务器类似“在服务器A上运行mySingletonA,在服务器B上运行mySingletonB”。为此,我看到可以通过JNDI
调用远程EJB。
为了满足约束2,我认为我需要使用GlassFish clustering
,因为需要在MySingleton的2个实例之间共享PersitenceContext。
不幸的是,我无法找到关于如何一起使用2个技术的任何参考资料(远程EJB和集群)。
我正在寻找有关此方案的首选架构的提示或建议,以及最终的一些实施指南。
答案 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适配器!