javax.naming.NameNotFoundException: on WebSphere Liberty - java

I'm trying to use a datasource configurated as a JNDI on a WebSphere Application Server Liberty however I'm getting the follwoing error:
javax.naming.NameNotFoundException: java:comp/env/jdbc/myapp/master
The configuration for the datasource in Websphere application server is:
<dataSource commitOrRollbackOnCleanup="commit" id="jdbc/myapp/master" jdbcDriverRef="ojdbc7" jndiName="jdbc/myapp/master">
<properties.oracle URL="jdbc:oracle:thin:#127.0.0.1:1521:xe" oracleRACXARecoveryDelay="0" password="xxxxxxxx" user="app_master">
</properties.oracle>
<connectionManager maxPoolSize="50"/>
</dataSource>
The connection to database is made via this code inside a servlet (jndi=jdbc/myapp/master):
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource ds = (DataSource) envCtx.lookup(jndi);
setConnection(ds.getConnection());
System.out.println(getConnection().toString() );
What am I doing wrong?

The java:comp/env requires resource reference. You have following options to solve that:
1) Use resource injection - so instead of looking up it directly (via InitialContext) just add the following in your servlet class
#Resource(lookup = "jdbc/myapp/master", name="jdbc/myapp/master")
private DataSource dataSource;
2) Define resource reference in your web.xml like
<resource-ref>
<description>my datasource</description>
<res-ref-name>jdbc/myapp/master</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>CONTAINER</res-auth>
</resource-ref>
or you can create just reference also via annotation in the code.
3) Use direct JNDI, without reference (not a Java EE best practice)
DataSource ds = (DataSource) initCtx.lookup("jdbc/myapp/master");

In addition to what is already stated in the other answer, you should also check that you have enabled the jndi-1.0 feature. This is a common cause of lookups not working in Liberty.
For example, in server.xml,
<featureManager>
<feature>jdbc-4.2</feature>
<feature>jndi-1.0</feature>
... other features that you use
</featureManager>
And if this, too, is not enough to get it working, you should also check the configuration of resources upon which the dataSource depends, such as the jdbcDriver with id of ojdbc7 which is referenced in the config snippet that you provided.

Related

How to make use of a DataSource via JNDI works?

there's some things I definitely don't understand while using JNDI.
This should simplify our Java developers' life, but this promise sounds false.
The simplest way tu use a database from within an application seems to build each time you need it (so, once per application) a datasource class giving you a connection or session you will use.
It's a tool class written in a few minutes where you have to declare the driver, url, login and password. And it's done.
The recommanded way is to rely on the server resources management, JNDI and all resources such as directory, etc.
But is it really usefull and simple ??
With Tomcat, you have to have to fully describe the datasource in server.xml, then declare it as a resource in context.xml.
server.xml
<GlobalNamingResources>
<Resource auth="Container" driverClassName="org.postgresql.Driver" maxIdle="30" maxTotal="100" maxWaitMillis="10000" name="jdbc/dsTriasEmployees" password="pwd" type="javax.sql.DataSource" url="jdbc:postgresql://localhost:5432/trias_employees" username="login"/>
</GlobalNamingResources>
context.xml
<ResourceLink name="jdbc/dsTriasEmployees" global="jdbc/dsTriasEmployees"
type="javax.sql.DataSource" />
Java side, you should be able to inject it thanks to a Context Lookup code ou a #Resource(mappedBy...) annotation.
DataSource datasource;
public Connection connectJNDI() {
try {
Context initContext = new InitialContext();
Context envContext = (Context) initContext.lookup("java:/comp/env");
datasource = (DataSource) envContext.lookup("jdbc/trias_employees");
Connection con = datasource.getConnection();
genericLogger.info("JNDI LOOKUP -> " + con);
return con;
} catch (Exception ex) {
genericLogger.error("JNDI LOOKUP -> " + ex);
return null;
}
But after doing that, you still have to deal with error messages telling you that it's not enough just like this one :
javax.naming.NoInitialContextException: Need to specify class name in environment or system property, or as an applet parameter, or in an application resource file: java.naming.factory.initial
I have read somewhere that I now should add a JNDI properties file and a declaration in the web.xml file like this :
web.xml
<resource-ref>
<description>
DB PostgreSQL
</description>
<res-ref-name>
jdbc/trias_employees
</res-ref-name>
<res-type>
javax.sql.DataSource
</res-type>
<res-auth>
Container
</res-auth>
</resource-ref>
But when I wanna test with jUnit, my web.xml is not usefull...
How many XML and properties files should I write just to respect the best practice that want me to delegate access to the datasource to the server ?
How many times will I have to duplicate all the informations related to url, pool connection, etc. ??
I've read 2 or 3 books on Java EE, 50 posts on StackOverFlow and dozens of forums and all the JNDI Resources HOW-TO on the Tomcat website.
But it still does not work...
Is there somewhere the full description of all I have to do to connect to my database using the JNDI process ?
Help me please, or I'll kill a kitten for each more minute I'm losing just to do my job in "the recommanded way".
Thanx by advance.
To test classes dependent on a DataSource or any other object provided by Tomcat via JNDI outside of Tomcat you could rely on TomcatJNDI. Point it to your server.xml and context.xml and it will initialize a JNDI environment with all the objects configured in the files.
TomcatJNDI tomcatJNDI = new TomcatJNDI();
tomcatJNDI.processServerXml(serverXmlFile)
tomcatJNDI.processContextXml(contextXmlFile);
tomcatJNDI.start();
Then lookup the datasource
DataSource ds = (DataSource) InitialContext.doLookup("java:comp/env/jdbc/trias_employee")
You can find out more about TomcatJNDI here.

How to bind a JDBC datasource to JNDI context "java:comp/env/jdbc" when not to use web.xml

How to bind a JDBC datasource to JNDI context java:comp/env/jdbc only using code-based approach.
We need to write resource-ref in the web.xml for binding a dataSource to JNDI local context java:comp/env/jdbc.
But I want to use only org.springframework.web.context.AbstractContextLoaderInitializer instead of web.xml(the old approach).
We know the method InitialContext#createSubcontext. But some application servers(e.g. Websphere) do not accept to edit the context java:comp/env/jdbc/.
Any solutions?
Versions:
Spring 4.0.7
Servlet 3.0
You could try a full programmatic approach using Spring's SimpleNamingContextBuilder:
SimpleNamingContextBuilder builder = new SimpleNamingContextBuilder();
DataSource ds = new DriverManagerDataSource(...);
builder.bind("java:comp/env/jdbc/myds", ds); // you control the datasource
builder.activate();
It's mainly there for test-purposes. If you choose to use it then you need to provide your own connection pool (e.g. Apache's Jakarta Commons DBCP).
I once used for testing when I deployed to cloudbees. see this blogpost
This works in "plain" Tomcat. I don't have a EE server to test with, but you could try it and see what happens (I guess the JNDI binding name has to be unique to the server though).
What is your application server?
See if this helps.
How to use JNDI DataSource provided by Tomcat in Spring?

Lookup a JDBC DataSource in WebSphere 8.5

I want to use a JDBC Connetion in my webapp which is configured in WebSphere. (Like this one here: How to use JDBC in JavaEE?)
I had used this DataSource before via JPA but our customer wants to have native SQL ... don't ask.
I found a lot of examples and tutorial (e.g. http://www.wickcentral.com/java/dl/ds_resreferencesetts_Websphere.pdf, Websphere JNDI lookup fails) but nothing want work.
The DataSource in the WebSphere has the JNDI-Name "jdbc/myDS"
I added a resource-ref to my web.xml:
<resource-ref>
<res-ref-name>jdbc/myDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
And I tryed to get the DataSource in my Dao:
ds = (DataSource) new InitialContext()
.lookup("java:comp/env/jdbc/myDS");
But what I get is a
com.ibm.wsspi.injectionengine.InjectionException: CWNEN0044E: A resource reference binding could not be found for the following resource references [jdbc/myDS], defined for the MyAPP component.
I tryed a lot. Did anyone sees the fault?
Did you match your web-app defined datasource with a Websphere defined datasource during installation? Websphere usually asks you to bind resources when they are detected on the installation process (If I remember correctly, it is in the step named "Map reference resources to resources").
Other common issue is a Websphere datasource in a different context (Cell/Node/Server) than your app, so it cannot be found at runtime.
You need to add the binding in ibm-web-bnd.xml:
<resource-ref name="jdbc/myDS" binding-name="jdbc/myDS" />

How to lookup a (JDBC) JNDI resource?

We have a personal java library which is deployed on a tomcat server (v5.5 & v6).
This library is shared with many web applications, so it was deployed on shared/lib in tomcat directory.
Exceptionaly, i have to create a new class into this library which lookup a jdbc datasource via JNDI.
For that, here my code :
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
DataSource dataSource = (DataSource) envCtx.lookup("jdbc/corp.xx.xx.xxxxDS");
All context are instantiated without problem. But when it lookup the jdbc datasource, i have an exception : Name jdbc not Found in Context
We are not in a webapp, is it a problem ?
Is it possible to declare a context.xml with a ResourceLink ? how ?
nb: the jndi is setted in server.xml (a resource in GlobalNamingResources)
<Context ...>
...
<ResourceLink name="linkToGlobalResource"
global="simpleValue"
type="java.lang.Integer"
...
</Context>
Where name is the new name (name relative to java:comp/env), global is the global jndi name configured in server.xml
So, from your code, look up linkToGlobalResource which will give you the linked global resource
Reference: http://tomcat.apache.org/tomcat-5.5-doc/config/context.html#Resource_Links
Answer Updated:
Your JNDI access will be from web-app and not shared jar because standalone jar does not have the concept of context.

How to map a datasource for a java web service

I'm trying to figure out how to use datasources for my web service. I have the oracle-ds.xml deployed on my jboss 4.2.3 server, and the datasources are showing as bounded to JNDI names java:TestDS, java:WeatherDS, etc.
I try doing an initialcontext.lookup but I can't find it. I tried referencing the resource in the web.xml but I get "java:WeatherDS has no valid JNDI binding"... I've tried referencing "java:/WeatherDS", "WeatherDS", "java:WeatherDS", "jdbc/WeatherDS" and some others, but I think I need to somehow map the reference name to the jndi name.
I found a snippet of code that says:
...
<resource-ref>
<res-ref-name>jdbc/DefaultDS</res-ref-name>
<jndi-name>java:/DefaultDS</jndi-name>
</resource-ref>
...
But, it doesn't say where this file is and what else is needed. I don't know if I need a resource reference for sure or not. Can anyone point me in the direction of some more complete information of how to access the datasource from the code once it has been deployed? I am trying to make it so the connections are pooled for my web service.
In JBoss-4.2.3 you define a datasource in an XML-File in folder [JBOSS_HOME]/server/[MYSERVER]/deploy/
Create a file in this folder with name: mydatasource-ds.xml.
XML-File content:
<datasources>
<local-tx-datasource>
<jndi-name>mydatasource</jndi-name>
<!-- Properties for SQLServer -->
<connection-url>jdbc:jtds:sqlserver://hostname:1433/db-name;TDS=8.0;lastUpdateCount=true;sendStringParametersAsUnicode=false</connection-url>
<driver-class>net.sourceforge.jtds.jdbc.Driver</driver-class>
<!-- Properties for SQLServer end -->
<user-name>name</user-name>
<password>pwd</password>
<min-pool-size>5</min-pool-size>
<max-pool-size>50</max-pool-size>
<idle-timeout-minutes>15</idle-timeout-minutes>
<blocking-timeout-millis>15000</blocking-timeout-millis>
</local-tx-datasource>
</datasources>
To can access these datasource from every application deployed in the same JBoss by normal JNDI lookup.
IMPORTANT: Use prefix java:/ in the jndi name in your code. Full JNDI-Name in your application for the datasource above is java:/mydatasource

Categories

Resources