Issue
I am working on a project where i have to call a function at fixed intervals which interacts with the database using jndi to provide some value. The project is working fine on tomcat but giving JndiLookupFailureException when deployed on Websphere. But if we call the same function using manual hit that is using url the function executes successfully on websphere without giving any exception of jndi. I think the problem is with the cron scheduler but not getting exact root cause.
Following are the details:
1) web.xml
<resource-ref>
<res-ref-name>jdbc/dummyJndi</res-ref-name>
<res-type>oracle.jdbc.pool.OracleDataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
2) database.xml
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
<property name="jndiName" value="java:comp/env/jdbc/dummyJndi" />
<property name="lookupOnStartup" value="false" />
<property name="cache" value="true" />
<property name="proxyInterface" value="javax.sql.DataSource" />
</bean>
3) scheduler.xml
<task:scheduled-tasks>
<task:scheduled ref="sampleService" method="getData"
cron="0 0/20 * * * ?" />
</task:scheduled-tasks>
<bean id="sampleService"
class="com.service.SampleService">
</bean>
4) exception on Websphere
org.springframework.jndi.JndiLookupFailureException: JndiObjectTargetSource failed to obtain new target object; nested exception is javax.naming.ConfigurationException: A JNDI operation on a "java:" name cannot be completed because the server runtime is not able to associate the operation's thread with any J2EE application component. This condition can occur when the JNDI client using the "java:" name is not executed on the thread of a server application request. Make sure that a J2EE application does not execute JNDI operations on "java:" names within static code blocks or in threads created by that J2EE application. Such code does not necessarily run on the thread of a server application request and therefore is not supported by JNDI operations on "java:" names. [Root exception is javax.naming.NameNotFoundException: Name comp/env/jdbc not found in context "java:".]
at org.springframework.jndi.JndiObjectTargetSource.getTarget(JndiObjectTargetSource.java:139)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:182)
at com.sun.proxy.$Proxy940.getConnection(Unknown Source)
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:381)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:455)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:463)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:471)
at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:476)
at org.springframework.jdbc.core.JdbcTemplate.queryForInt(JdbcTemplate.java:485)
Solution
I am giving some suggestion. You can try it one by one. Hope it may help you.
Suggestion#1:
In your database.xml, use
<property name="jndiName" value="jdbc/dummyJndi" />
instead of
<property name="jndiName" value="java:comp/env/jdbc/dummyJndi" />
Sometimes, it solves the issue.
Resource Link:
Suggestion#2
Issue:
"javax.naming.NamingException - Name comp/env/jdbc not found in context "java:"
Root Cause Analysis:
The most likely cause of this exception is that the application does an indirect JNDI lookup, but a resource reference does not exist for the resource that is looked up. To provide some background information, there are two different types of JNDI lookups in WebSphere Application Server: A direct, or global, JNDI lookup occurs when the application looks up the physical JNDI name of a resource that is bound to the namespace. For example, if the JNDI name of a data source is "jdbc/myDS", the lookup would look like this:
DataSource ds = (DataSource)ctx.lookup("jdbc/myDS");
An indirect, or local, JNDI lookup occurs when the application looks up a resource reference which maps to the physical JNDI name. A resource reference is defined in the application deployment descriptor, web.xml for a Web module, ejb-jar.xml for an EJB module, or application-client.xml for an application client module. For example, if the resource reference name is "jdbc/myDSresref", the lookup would look like this:
DataSource ds = (DataSource)ctx.lookup("java:comp/env/jdbc/myDSresref");
Indirect JNDI lookups are considered a J2EE best practice. The advantage of an indirect JNDI lookup is that it makes your applications easier to maintain. If the actual JNDI name of a resource changes, no changes need to be made to your application. This is because the JNDI name of the resource is stored in the resource reference, not in the application code.
If a resource reference does not exist in the application module, the JNDI lookup will fail with the javax.naming.NamingException mentioned above. It is also important to note that an indirect JNDI lookup can only be done from an application within a J2EE container (Web module, EJB module, or application client module).
Resolving the problem:
To resolve the problem, you'll need to create a resource reference in the deployment descriptor for your Web, EJB, or application client module, and map it to the physical JNDI name for your resource. This can be done using the Application Server Toolkit (AST), WebSphere Studio Application Developer (WSAD), or Rational Application Developer (RAD).
Creating or changing a resource reference http://pic.dhe.ibm.com/infocenter/wasinfo/v8r0/index.jsp?topic=/com.ibm.websphere.nd.doc/info/ae/ae/tatk_crtresref.html
The name of the resource reference is the part of the JNDI name that comes after " java:comp/env" when the indirect JNDI lookup is done. When configuring the resource reference, the physical JNDI name of the resource is set as the JNDI Binding.
Resource Link:
http://www-01.ibm.com/support/docview.wss?uid=swg21106933
Suggestion#3:
Spring boot JNDI datasource lookup failure - Name comp/env/jdbc not found in context "java:"
Answered By - SkyWalker