OSGI JNDI 是否允许与来自非 OSGI 代码的 JNDI 调用共存?

2022-09-04 04:53:30

OSGI Enterprise Release 5 规范的第 126 章提到了兼容性:

“支持 Java SE 和 Java EE 客户端使用的传统 JNDI 编程模型。

和使用不识别OSGI的代码:

“不了解OSGi的客户端和JNDI上下文提供程序使用静态方法连接到JRE JNDI实现。类提供从提供程序访问上下文,提供程序使用静态命名管理器方法执行对象转换和查找 URL 上下文。这种传统模型不了解OSGi,因此只有在管理这种缺乏OSGi意识的后果时才能可靠地使用。

但是我不清楚这段文字是只适用于在OSGI捆绑包内执行的“遗留”代码,还是也适用于OSGI容器外的代码,在OSGI容器嵌入到应用程序中的场景中。

在嵌入场景中,OSGI 容器外部和内部都可能存在执行 JNDI 调用的应用程序代码,并且当它们在同一 JVM 中执行时,它们将共享 JNDI 实现。

问题:在嵌入式 OSGI 容器中运行的 OSGI JNDI 实现应该允许容器外部的 OSGI 无意识代码像往常一样执行其 JNDI 调用,还是需要一些移植到“OSGI 感知”?

我自己用Apache Karaf 2.3.0(它使用Apache Aries JNDI 1.0.0)尝试一下,这似乎不起作用,因为Apache Aries需要JNDI客户端调用来自OSGI捆绑包。
部分堆栈跟踪:

javax.naming.NoInitialContextException: The calling code's BundleContext could not be determined.
    at org.apache.aries.jndi.OSGiInitialContextFactoryBuilder.getInitialContext(OSGiInitialContextFactoryBuilder.java:46)
    at javax.naming.spi.NamingManager.getInitialContext(NamingManager.java:684)
    at javax.naming.InitialContext.getDefaultInitCtx(InitialContext.java:307)
    at javax.naming.InitialContext.init(InitialContext.java:242)
    at javax.naming.InitialContext.<init>(InitialContext.java:192)

问题:这是正确的行为,还是我可以参考的规范中有一部分被此限制所违反?


答案 1

在尝试在Weblogic上部署Apache Karaf时,我遇到了同样的问题。我们通过一个 servlet 桥接使用 karaf - 在 weblogic 中部署了一场战争,它将所有 http 请求桥接到 karaf。

我在 weblogic 上运行以下应用程序:

  1. app1 (使用 JNDI)
  2. 应用2
  3. 卡拉夫桥(对卡拉夫的桥梁请求)

一旦卡拉夫启动,在卡拉夫内部运行的Aries JNDI实现就会将Javax.nameing.NameingManager中的InitialContextFactoryBuilder设置为自己的实现。NameManager 持有对初始上下文工厂构建器的静态引用,因此,无论哪个实现(无论它是否在 OSGI 环境中运行)设置此静态引用,都将成为 JNDI 提供程序。

在我的情况下,当app1(非OSGI)尝试做一个新的InitialContext时,Aries JNDI尝试使用BundleContext解决它并失败。

我使用一些非常丑陋的技巧修复了这个问题,这些技巧涉及从jre中提取javax.name软件包并将其作为kaf中的捆绑包安装。

所以你的问题的答案是:我认为问题真的在jre上,而不是OSGI关于如何管理JNDI查找。


答案 2

我不确定我是否正确理解了这个问题...JNDI 是一个服务提供程序接口,它需要一些底层实现来运行。您需要做的就是将其预配为OSGI容器。

我建议使用JNDI所需的所有jar创建单个捆绑包并导出所有包。然后使用动态导入:*来使用它。它在我们的案例中起作用(Eclipse RCP应用程序与JBoss 5 JNDI用于EJB调用)。

但是,如果您在容器内部和外部需要 JNDI,并且您不想在类加载方面遇到麻烦,我建议您将所有 jar 添加到应用程序类路径中。这样,它应该可以在整个应用程序中访问。


推荐