What does java:comp/env/ do?

SpringJdbcJndiFactory

Spring Problem Overview


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".

Spring Solutions


Solution 1 - Spring

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");

Solution 2 - Spring

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>

Solution 3 - Spring

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDannyView Question on Stackoverflow
Solution 1 - SpringcherouvimView Answer on Stackoverflow
Solution 2 - SpringFilip SpiridonovView Answer on Stackoverflow
Solution 3 - SpringThiago Leão MoreiraView Answer on Stackoverflow