我想编写一个包含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存在于一个容器中,但未来可能会移动到其他容器。
根据大卫的建议,我做了一些改变。代码是POJO,而不是JUnit代码。它不使用@LocalClient和initialContext.bind(“inject”,this); (我把2个代码放在我的JUnit代码中)
放置资源\ META-INF \ application-client.xml(仅包含)
放置resources \ 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
查找代码
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.
基于David的评论,在Java EE6之前,我认为唯一的解决方案是使用服务定位器和一些配置在WebLogic和OpenEJB之间使用不同的JNDI。以下是测试结果。
DB: WebLogic:OrderDB,OpenEJB:openejb:Resource / jdbc / OrderDB
事务管理器: WebLogic:javax.transaction.TransactionManager,OpenEJB:java:comp / TransactionManager
EJB :它们都只是查找没有任何前缀的EJB名称
答案 0 :(得分:2)
更新中的问题是一个非常不同的问题,因此发布了不同的答案。
它的长短是在Java EE 6之前,没有全局JNDI。因此,字面上的问题是“什么是 JNDI名称x”是一个无法回答的问题。每个EJB都有自己的私有JNDI命名空间,“POJO”根本没有任何命名空间,它们使用任何EJB调用它的JNDI命名空间。因此,要使“java:comp / env / myDataSource”尽可能显示为全局,您必须为应用程序中的每个EJB声明该引用。
这为用户创建的配置工作量非常具有破坏性。在Java EE 6中,最终有全局JNDI和三个新的标准名称空间,java:module
,java:app
和java:global
。 Java EE 6之前存在的任何全局JNDI功能都是特定于供应商的,并且是不可移植的。
在OpenEJB中针对给定名称执行全局JNDI查找的特定于供应商和不可移植的方法是查找openejb:Resource/jdbc/OrderDB
在OpenEJB中,我们故意不像某些供应商那样支持jdbc/OrderDB
或java:jdbc/OrderDB
等非标准查找。 OpenEJB中全局名称的必需前缀为openejb:
。
JNDI非常复杂且令人困惑,并且使非便携式名称看起来像便携式名称并不会给用户带来任何好处。如果某种命名方式不可移植并且要创建供应商锁定,它应该看起来像它。因此,使用openejb:
前缀,您可以访问全局所需的任何内容,但至少可以清楚地知道您正在执行的操作是不可移植的,并且不应该在没有进行某些修改的情况下在其他平台中工作。
答案 1 :(得分:1)
请注意,您可以使用标准jndi.properties
文件将100%通常作为属性传入的配置外部化为IntitialContext
您仍然可以使用服务定位器模式,因为它可以使您的代码看起来更好,也许更容易维护,但实际的服务器连接信息可以很容易地外化。
您只需要确保jndi.properties
文件位于客户端的根路径(即不在META-INF
目录中)的类路径中。 IntialContext
会找到并加载它。传递到IntialContext
构造函数的任何属性都将覆盖通过jndi.properties
在OpenEJB端,应该可以更改JNDI name format,使其与WebLogic格式匹配。如果没有,请告诉我们,我们可以将任何缺失的元数据添加到格式化程序中,以便可以完全匹配它。
答案 2 :(得分:0)
您不能只使用默认上下文吗?然后您不必指定具体的实现,您可以通过标准引用进行查找。
否则我认为你留下了某种属性文件来确定运行时的上下文细节。