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

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

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

和使用OSGI不知道的代码:

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

但是我不清楚这个文本是仅适用于在OSGI包内执行的“遗留”代码,还是OSGI容器外部的代码,在OSGI容器嵌入应用程序的情况下。

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

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

使用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.(InitialContext.java:192) 

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

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

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

  1. app1(使用JNDI)
  2. APP2
  3. karaf-bridge(桥梁请求卡拉夫)

一旦karaf启动,在Karaf内部运行的Aries JNDI实现就将javax.naming.NamingManager中的InitialContextFactoryBuilder设置为它自己的实现。 NamingManager保存对初始上下文工厂构建器的静态引用,因此无论是否在OSGI环境中运行,无论哪个实现设置此静态引用都将成为JNDI提供程序。

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

我使用一些非常丑陋的黑客来解决这个问题,这些黑客涉及从jre中提取javax.naming包并将其作为捆绑包安装在karaf中。

所以问题的答案是:我认为这个问题确实存在于jre中,而不是OSGI关于如何管理JNDI查找。

我不确定我是否正确理解了这个问题… JNDI是一个服务提供者接口,它需要一些底层实现才能运行。 您需要做的就是为它配置OSGI容器。

我建议使用JNDI所需的所有jar创建单个bundle并导出所有包。 然后使用Dynamic-Import:*来使用它。 它适用于我们的情况(Eclipse RCP应用程序,JBoss 5 JNDI用于EJB调用)。

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

Apache Aries似乎已经考虑过这个并提供了JRE初始上下文工厂构建器(org.apache.aries.jndi.JREInitialContextFactoryBuilder)的实现,它似乎可行。 但是,为了实现这一点,我必须更改注册JVM范围的初始上下文工厂构建器的Aries代码。 可能有另一种(可能更好)的方法来实现这一目标。 但这似乎有效。

另请注意,问题不会停留在NamingManager中设置的InitialContextFactoryBuilder。 ObjectFactoryBuilder也出现了同样的问题(在NamingManager中再次将JVM设置为JVM)。 根据您尝试连接的JNDI提供程序,您可能还需要更改Aries JNDI代码的那部分。 例如,对于Tibco EMS JNDI连接,我不得不从Aries调整OSGiObjectFactoryBuilder的代码以返回特定于Tibco的ObjectFactory。 这可以使用Context.OBJECT_FACTORIES环境值轻松推广。

我为此提出了一个JIRA – https://issues.apache.org/jira/browse/ARIES-1127