124

I just spent too much time of my day trying to figure out some errors when hooking up some JNDI factory bean. The problem turned out to be that instead of this...

<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="java:comp/env/jdbc/loc"/>
</bean>

I had actually written this...

<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="jdbc/loc"/>
</bean>

I infer that the java:comp/env/ perhaps references some environment variable and makes it so that, ultimately, my context file is looked at. The only difference is java:comp/env/. From an expert's mouth, what does that do?

Without the java:comp/env/ prefix in the value, I would get an error that said "Name jdbc is not bound in this Context".

Alexander Pozdneev
  • 1,289
  • 1
  • 13
  • 31
Danny
  • 3,670
  • 12
  • 36
  • 45
  • 3
    Which one did you initially use? Your question implies that you was incorrectly using the second example (`jdbc/loc` and thus `java:comp/env/jdbc/loc` is correct), while the answer of cherouvim implies that you was incorrectly using the first example (`java:comp/env/jdbc/loc` and thus `jdbc/loc` is correct). Regardless, the real answer is: it depends on the **current** context. – BalusC Nov 04 '10 at 19:30
  • 1
    The one that did not work was indeed missing java:comp/env/jdbc/loc, as implied. The context file that was pointed to included the "loc" resource. What are the possibilities for "current" contexts? – Danny Nov 04 '10 at 21:20
  • 1
    I answered this here: https://stackoverflow.com/a/66325569/1051589. – joker Feb 23 '21 at 00:55

3 Answers3

105

Quoting https://web.archive.org/web/20140227201242/http://v1.dione.zcu.cz/java/docs/jndi-1.2/tutorial/beyond/misc/policy.html

At the root context of the namespace is a binding with the name "comp", which is bound to a subtree reserved for component-related bindings. The name "comp" is short for component. There are no other bindings at the root context. However, the root context is reserved for the future expansion of the policy, specifically for naming resources that are tied not to the component itself but to other types of entities such as users or departments. For example, future policies might allow you to name users and organizations/departments by using names such as "java:user/alice" and "java:org/engineering".

In the "comp" context, there are two bindings: "env" and "UserTransaction". The name "env" is bound to a subtree that is reserved for the component's environment-related bindings, as defined by its deployment descriptor. "env" is short for environment. The J2EE recommends (but does not require) the following structure for the "env" namespace.

So the binding you did from spring or, for example, from a tomcat context descriptor go by default under java:comp/env/

For example, if your configuration is:

<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="foo"/>
</bean>

Then you can access it directly using:

Context ctx = new InitialContext();
DataSource ds = (DataSource)ctx.lookup("java:comp/env/foo");

or you could make an intermediate step so you don't have to specify "java:comp/env" for every resource you retrieve:

Context ctx = new InitialContext();
Context envCtx = (Context)ctx.lookup("java:comp/env");
DataSource ds = (DataSource)envCtx.lookup("foo");
Community
  • 1
  • 1
cherouvim
  • 31,725
  • 15
  • 104
  • 153
  • I thought I had understood this correctly, but further comments made me realize I had done so backward. If the tomcat context descriptor went, by default, under java:comp/env, wouldn't that mean that I can omit the java:comp/env from the value? In my case, I had to add it to make the "Name jdbc is not bound in this Context" error go away. – Danny Nov 04 '10 at 21:49
  • 4
    You bind using "foo" and lookup using "java:comp/env/foo". Have a look at http://blog.cherouvim.com/javax-sql-datasource-exposed-through-jndi/ – cherouvim Nov 05 '10 at 07:57
  • 3
    The above link is from the standalone JNDI tutorial, originally available on: http://docs.oracle.com/javase/jndi/tutorial/beyond/misc/policy.html. – Danilo Piazzalunga Aug 20 '13 at 16:57
  • what if there are more /-es in your lookup? Like: "java:com/env/foo/bar", is your jndiName value "foo/bar" or "foo.bar"? – Pieter De Bie Jun 05 '15 at 07:15
  • The correct jndiName value would "foo/bar" @PieterDeBrie. – tftdias Oct 29 '15 at 23:53
  • The link is dead, use the one @DaniloPiazzalunga quotes. – ᴠɪɴᴄᴇɴᴛ Jul 12 '16 at 15:58
37

There is also a property resourceRef of JndiObjectFactoryBean that is, when set to true, used to automatically prepend the string java:comp/env/ if it is not already present.

<bean id="someId" class="org.springframework.jndi.JndiObjectFactoryBean">
  <property name="jndiName" value="jdbc/loc"/>
  <property name="resourceRef" value="true"/>
</bean>
SteveT
  • 183
  • 2
  • 10
Filip Spiridonov
  • 34,332
  • 4
  • 27
  • 30
3

After several attempts and going deep in Tomcat's source code I found out that the simple property useNaming="false" did the trick!! Now Tomcat resolves names java:/liferay instead of java:comp/env/liferay

  • Could you provide a complete example, including the resource definition? I did not manage to set this up successfully with Tomcat 8.5 - a more comprehensive example would help me see my mistake, maybe. – RobertG Jul 16 '19 at 01:53