What does java:comp/env/ do?
SpringJdbcJndiFactorySpring 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
> 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