2

我想编写一个有 2 个 EJB 的应用程序。此应用程序可以在 OpenEJB 和 WebLogic 10.3 中运行。两个 EJB 都是 EJB 3.0。

我知道如何在 OpenEJB 和 WebLogic 中实现,但问题是我想使用相同的代码部署到这两个环境。我认为问题在于如何进行 JNDI 查找,因为 WebLogic 的 Context.INITIAL_CONTEXT_FACTORY 是 weblogic.jndi.WLInitialContextFactory 而 OpenEJB 不是。

当前的想法是第一个 EJB 使用服务定位器来查找第二个 EJB,并且服务定位器将在 2 个环境中读取不同的 INI。还有其他建议吗?有没有一个解决方案我可以只使用注释,不需要使用外部 INI 文件。

这 2 个 EJB 存在于一个容器中,但将来有可能将一个移到另一个容器中。

2011/10/06 更新

根据大卫的建议,我放了一些零钱。该代码是 POJO,而不是 JUnit 代码。它不使用 @LocalClient 和 initialContext.bind("inject", this); (我把 2 代码放在我的 JUnit 代码中)

  1. 把resources\META-INF\application-client.xml(只包含)

  2. 把资源\jndi.properties

    jdbc/OrderDB = new://Resource?type=DataSource
    jdbc/OrderDB.JdbcDriver = oracle.jdbc.OracleDriver
    jdbc/OrderDB.JdbcUrl = jdbc:oracle:thin:@*.*.*.*:1521:test
    jdbc/OrderDB.JtaManaged = false
    jdbc/OrderDB.UserName = test
    jdbc/OrderDB.Password = test
    
  3. 查找代码

    InitialContext ctx= new InitialContext();
    ctx.lookup("jdbc/" + name);
    

以下是日志,OpenEJB 为数据库创建 JNDI。我也是用Eclipse调试模式查看“ctx”的内容,在MyProps中找到“jdbc/OrderDB”

INFO - Configuring Service(id=jdbc/OrderDB, type=Resource, provider-id=Default JDBC Database)

但最后我仍然无法查找它。我也尝试使用 ctx.lookup(name), ctx.lookup("java:comp/env/jdbc/" + name) 结果是一样的。

javax.naming.NameNotFoundException: Name "jdbc/OrderDB" not found.

2011/10/12 更新

根据 David 的评论,在 Java EE6 之前,我认为唯一的解决方案是使用服务定位器和一些配置在 WebLogic 和 OpenEJB 之间使用不同的 JNDI。以下是测试结果。

DB: WebLogic:OrderDB,OpenEJB:openejb:Resource/jdbc/OrderDB

事务管理器: WebLogic:javax.transaction.TransactionManager,OpenEJB:java:comp/TransactionManager

EJB:他们都只是查找没有任何前缀的 EJB 名称

4

3 回答 3

2

更新中的问题是一个非常不同的问题,因此发布不同的答案。

Java EE 6 之前没有全局 JNDI

总而言之,在 Java EE 6 之前,没有全局 JNDI。因此,从字面上看,“ xJNDI 名称是什么”这个问题是一个无法回答的问题。每个 EJB 都有自己的私有 JNDI 名称空间,而“POJO”根本没有任何名称空间,它们使用任何 EJB 调用它的 JNDI 名称空间。因此,要使“java:comp/env/myDataSource”尽可能地显示为全局,您必须为应用程序中的每个 EJB 声明该引用。

这为用户带来的配置工作量非常大。在 Java EE 6 中,终于有了 Global JNDI 和三个新的标准命名空间java:modulejava:appjava:global. 在 Java EE 6 之前存在的任何 Global JNDI 功能都是特定于供应商且不可移植的。

在 OpenEJB 中为给定名称执行全局 JNDI 查找的特定于供应商且不可移植的方法是查找openejb:Resource/jdbc/OrderDB

直言不讳

在 OpenEJB 中,我们故意不支持像某些供应商那样jdbc/OrderDB的非标准查找。java:jdbc/OrderDBOpenEJB 中全局名称所需的前缀是openejb:.

JNDI 足够复杂和令人困惑,使不可移植名称看起来像可移植名称对用户没有任何好处。如果某种命名风格不可移植并且会造成供应商锁定,它应该看起来像它。因此,使用openejb:前缀,您可以在全局范围内访问您需要的任何内容,但至少很明显,您正在做的事情是不可移植的,不应该期望在没有一些修改的情况下在其他平台上工作。

于 2011-10-08T23:33:04.263 回答
1

请注意,jndi.properties您可以使用一个标准文件将通常作为属性传入的配置的 100% 外部化到IntitialContext

您仍然可以使用服务定位器模式,因为它可以使您的代码看起来更好一些,并且可能更易于维护,但实际的服务器连接信息可以很容易地外部化。

您只需要确保该jndi.properties文件位于客户端的类路径的根目录中(即不在META-INF目录中)。将IntialContext找到它并加载它。传递给构造函数的任何属性IntialContext都将简单地覆盖那些通过jndi.properties

在 OpenEJB 端,应该可以更改JNDI 名称格式,使其与 WebLogic 格式匹配。如果没有,请告诉我,我们可以将任何丢失的元数据添加到格式化程序中,以便可以完全匹配它。

于 2011-09-26T20:02:58.987 回答
0

你不能只使用默认上下文吗?然后您不必指定具体的实现,您可以通过标准参考进行查找。

否则,我认为您会留下某种属性文件来确定运行时的上下文详细信息。

于 2011-09-20T16:25:15.107 回答