问题
Chapter 126 of the OSGI Enterprise Release 5 specification mentions compatibility:
"Support the traditional JNDI programming model used by Java SE and Java EE clients."
and use of OSGI-unaware code:
"Clients and JNDI Context providers that are unaware of OSGi use static methods to connect to the JRE JNDI implementation. The InitialContext class provides access to a Context from a provider and providers use the static NamingManager methods to do object conversion and find URL Contexts. This traditional model is not aware of OSGi and can therefore only be used reliably if the consequences of this lack of OSGi awareness are managed."
but it is not clear to me if this text only applies to "legacy" code executed inside an OSGI bundle, or also to code outside the OSGI container, f ex in a scenario where the OSGI container is embedded in an application.
In an embedding scenario, there may be application code both outside and inside the OSGI container that performs JNDI calls, and as they execute in the same JVM they will share JNDI implementation.
Question: Should an OSGI JNDI implementation running in an embedded OSGI container allow OSGI-unaware code outside the container to perform its JNDI calls like usual, or is some porting to "OSGI-awareness" required?
Trying this out myself with Apache Karaf 2.3.0 (which uses Apache Aries JNDI 1.0.0) this doesn't seem to work, as Apache Aries requires JNDI client calls to originate from an OSGI bundle.
Partial stacktrace:
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)
Question: Is this correct behaviour, or is there a section of the specification I can refer to that is violated by this limitation?
回答1:
I ran into same issue when trying to deploy Apache Karaf on Weblogic. We use karaf through a servlet bridge - a war is deployed in weblogic which bridges all http requests to karaf.
I am running with the the following applications on weblogic:
- app1 (uses JNDI)
- app2
- karaf-bridge (bridges requests to Karaf)
As soon as karaf starts the Aries JNDI implementation running inside Karaf sets InitialContextFactoryBuilder inside javax.naming.NamingManager to its own implementation. NamingManager holds a static reference to the initial context factory builder, so whichever implementation, irrespective of whether its running in an OSGI environment, sets this static reference becomes the JNDI provider.
In my case when app1 (non-OSGI) tries to do a new InitialContext, Aries JNDI tries to resolve it using the BundleContext and fails.
I fixed this using some very ugly hacks that involved extracting the javax.naming package from jre and installing it as a bundle in karaf.
So the answer to your question: I think the issue is really in the jre and not with OSGI on how JNDI lookup is managed.
回答2:
I'm not sure if I understand the problem correctly... JNDI is a Service Provider Interface, and it needs some underlying implementation to run with. All you need to do is to provision it the OSGI container.
I would recommend creating single bundle with all jars needed by JNDI and export all packages. Then use Dynamic-Import: * to use it. It worked in our case (Eclipse RCP application with JBoss 5 JNDI used for EJB calls).
However if you need JNDI inside and outside of the container and you don't want to struggle with Classloading, I would recommend adding all jars to the applications classpath. This way it should be accessible in whole your application.
回答3:
Apache Aries seems to have thought about this and have provided an implementation of JRE initial context factory builder (org.apache.aries.jndi.JREInitialContextFactoryBuilder) which seems to work. However, for this to work, I had to change Aries code that registers the JVM wide initial context factory builder. There may be another (and possibly better) way of achieving this. But this seemed to work.
Also, note that the problem does not stop at InitialContextFactoryBuilder being set in NamingManager. The same issue arises for ObjectFactoryBuilder (which is again set JVM wide in NamingManager). Depending on the JNDI provider you are trying to connect to, you may need to change that part of Aries JNDI code as well. e.g. for Tibco EMS JNDI connection, I had to tweak the code for OSGiObjectFactoryBuilder from Aries to return a Tibco specific ObjectFactory. This can be easily generalized using Context.OBJECT_FACTORIES environment value.
I've raised a JIRA for the same - https://issues.apache.org/jira/browse/ARIES-1127
来源:https://stackoverflow.com/questions/13682882/does-osgi-jndi-allow-coexistence-with-jndi-calls-from-non-osgi-code