EJB调用WebLogic和OpenEJB中的EJB
我想编写一个有 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
根据David的建议,我做了一些改变。该代码是 POJO,而不是 JUnit 代码。它不使用@LocalClient和initialContext.bind(“inject”, this); (我将2代码放在我的JUnit代码中)
Put resources\META-INF\application-client.xml (仅包含)
放入资源\jndi.properties
jdbc/OrderDB = new://Resource?type=DataSource jdbc/OrderDB.JdbcDriver = oracle.jdbc.OracleDriver jdbc/OrderDB.JdbcUrl = jdbc:oracle:thin:@*.*.*.*:1521:测试 jdbc/OrderDB.JtaManaged = false jdbc/OrderDB.UserName = 测试 jdbc/OrderDB.Password = 测试
查找代码
InitialContext ctx= new InitialContext(); ctx.lookup("jdbc/" + 名称);
如下是日志,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。以下是测试结果。
数据库: WebLogic:OrderDB、OpenEJB:openejb:Resource/jdbc/OrderDB
事务管理器: WebLogic:javax.transaction.TransactionManager、OpenEJB:java:comp/TransactionManager
EJB:两者都只是查找没有任何前缀的EJB名称
I want to write an application which has 2 EJBs. This application can run in both OpenEJB and WebLogic 10.3. Both of the EJB are EJB 3.0.
I know how to implement in both OpenEJB and WebLogic, but the problem is I want to use the same code to deploy to both environments. I think the problem is that how to do JNDI lookup, because WebLogic's Context.INITIAL_CONTEXT_FACTORY is weblogic.jndi.WLInitialContextFactory but OpenEJB is not.
Current idea is the 1st EJB use a service locator to lookup the 2nd EJB and the service locator will read different INI in 2 environments. Is there any other suggestion? Is there a solution I can just use annotation, no need to use external INI files.
The 2 EJBs live in one container, but it's possible one will be move to other container in the future.
Update on 2011/10/06
By David's suggestion, I put some change. The code is a POJO, not JUnit code. It doesn't use @LocalClient and initialContext.bind("inject", this); (I put the 2 code in my JUnit code)
Put resources\META-INF\application-client.xml (only contain )
Put 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
Lookup code
InitialContext ctx= new InitialContext(); ctx.lookup("jdbc/" + name);
The following is the log, OpenEJB creates the JNDI for the database. I also use Eclipse debug mode to see the content of "ctx" and find "jdbc/OrderDB" in MyProps
INFO - Configuring Service(id=jdbc/OrderDB, type=Resource, provider-id=Default JDBC Database)
But finally I still cannot lookup it. I also try to use ctx.lookup(name), ctx.lookup("java:comp/env/jdbc/" + name) and the result is the same.
javax.naming.NameNotFoundException: Name "jdbc/OrderDB" not found.
Update on 2011/10/12
Base on David's comment, before Java EE6, I think the only solution is to use a service locator and some configuration to use different JNDI between WebLogic and OpenEJB. The following is the test result.
DB: WebLogic: OrderDB, OpenEJB: openejb:Resource/jdbc/OrderDB
Transaction manager: WebLogic: javax.transaction.TransactionManager, OpenEJB: java:comp/TransactionManager
EJB: Both of them just lookup the EJB name without any prefix
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
更新中的问题是一个非常不同的问题,因此发布不同的答案。
Java EE 6 之前没有全局 JNDI
总而言之,在 Java EE 6 之前,没有全局 JNDI。因此,从字面上看,“x 的 JNDI 名称是什么”这个问题是一个无法回答的问题。每个 EJB 都有自己的私有 JNDI 命名空间,而“POJO”根本没有任何命名空间,它们使用任何 EJB 调用它的 JNDI 命名空间。因此,为了使“java:comp/env/myDataSource”尽可能全局化,您必须为应用程序中的每个 EJB 声明该引用。
这给用户带来的配置工作量是相当大的。在 Java EE 6 中,终于有了 Global 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:
前缀,您可以在全局范围内访问您需要的任何内容,但至少可以清楚的是,您所做的事情是不可移植的,并且不应期望在不进行某些修改的情况下在其他平台上工作。The question in the update is a very different question, so posting a different answer.
No Global JNDI prior to Java EE 6
The long and short of it is that prior to Java EE 6, there is no global JNDI. So it is quite literally the case that the question "what is the JNDI name of x" is an unanswerable question. Each EJB has its own private JNDI namespace and "POJOs" don't have any namespace at all, they use the JNDI namespace of whatever EJB invoked it. So to make "java:comp/env/myDataSource" appear as global as possible, you have to declare that reference for every single EJB in the application.
The amount of configuration work this creates for users is quite devastating. In Java EE 6 there is finally Global JNDI and three new standard namespaces,
java:module
,java:app
andjava:global
. Any Global JNDI functionality existing prior to Java EE 6 is vendor-specific and non-portable.The vendor-specific and non-portable way to do a Global JNDI lookup in OpenEJB for the given name would be to lookup
openejb:Resource/jdbc/OrderDB
Calling a spade a spade
In OpenEJB we deliberately do not support non-standard lookups like
jdbc/OrderDB
orjava:jdbc/OrderDB
as some vendors do. The required prefix for global names in OpenEJB isopenejb:
.JNDI is complex and confusing enough and making non-portable names look like portable names doesn't do users any favors. If a certain style of naming is not portable and going to create vendor lock-in, it should look like it. So with the
openejb:
prefix, you can access anything you need globally but it is at least clear that what you are doing is not portable and should not be expected to work in other platforms without some modification.请注意,有一个标准
jndi.properties
文件,您可以使用它来外部化通常作为属性传递给IntitialContext
的 100% 配置。您仍然可以使用服务定位器模式因为它可以使您的代码看起来更好一点,并且可能更易于维护,但实际的服务器连接信息可以轻松外部化。
您只需确保
jndi.properties
文件位于客户端类路径的根目录中(即不在META-INF
目录中)。IntialContext
将找到它并加载它。传递到 IntialContext 构造函数中的任何属性都将简单地覆盖通过 jndi.properties 传递的属性。在 OpenEJB 端,应该可以更改 JNDI 名称格式,以便与 WebLogic 格式匹配。如果没有,请告诉我,我们可以将任何丢失的元数据添加到格式化程序中,以便可以完全匹配它。
Note that there is a standard
jndi.properties
file you can use to externalize 100% of the config normally passed in as properties to theIntitialContext
You can still use a service locator pattern as it can make your code look a little nicer and perhaps easier to maintain, but the actual server connection information can be easily externalized.
You just need to make sure the
jndi.properties
file is on the client's classpath at the root (i.e. not in aMETA-INF
directory). TheIntialContext
will find it and load it. Any properties passed into theIntialContext
constructor will simply override those passed in viajndi.properties
On the OpenEJB side it should be possible to change the JNDI name format so that it matches the WebLogic format. If not, let me know and we can add any missing meta-data to the formatter so that it is possible to match it exactly.
不能只使用默认上下文吗?然后您不必指定具体的实现,您可以通过标准参考进行查找。
否则,我认为您会留下某种属性文件来确定运行时的上下文详细信息。
Can't you just use the default context? Then you don't have to specify the specific implementation and you can do the lookup via a standard reference.
Otherwise I think you are left with some sort of properties file to determine the context details at runtime.