WebSphere: JNDI Context Lookup Failure - websphere

I have the following...
Context aContext = = new InitialContext(settings);
aContext.lookup("java:comp/env/DB2_DB");
Also tried...
aContext.lookup("DB2_DB");
web.xml
<resource-ref>
<description>
</description>
<res-ref-name>DB2_DB</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
<mapped-name>DB2_DB</mapped-name>
</resource-ref>
then in my ibm-web-bnd.xml...
<resource-ref name="DB2_DB" binding-name="jdbc/DB2DB" />
In Websphere I see the binding name in resources>JDBC>Data Sources
But when I run my application I see...
Caused by: javax.naming.NameNotFoundException: Context: Node04Cell/nodes/Node04/servers/server1, name: DB2_DB: First component in name DB2_DB not found. [Root exception is org.omg.CosNaming.NamingContextPackage.NotFound: IDL:omg.org/CosNaming/NamingContext/NotFound:1.0]^M
This is a port project from WAS6-8.5

Well, this question is quite old, and I see that there's no accepted answer yet, so.
Here is what really happens:
Your code executes a JNDI lookup to java:comp/env/DB2_DB.
WebSphere uses the WAS-proprietary deployment descriptor (ibm-web-bnd.xml) to "translate" the application binding DB2_DB into a real name in the WebSphere JNDI tree (jdbc/DB2DB).
WebSphere looks up jdbc/DB2DB and returning it to the caller.
You are getting a NameNotFoundException on the first lookup - the lookup of java:comp/env/DB2_DB. The problem is not with finding jdbc/DB2DB; it's with finding DB2_DB inside your component's environment.
Your deployment descriptor looks OK to me, so I'm guessing that the reason for your problem is this:
Context aContext = new InitialContext(settings);
You are constructing an InitialContext instance by providing a Hashtable. The Hashtable is often useful when you need to provide special parameters for the construction, but you must know when to use it and when to avoid it. Code that runs inside a JavaEE container and needs simple access to the container's JNDI tree rarely, if ever, should provide any Hashtable to the InitialContext constructor.
I wouldn't be surprised if those settings that you're passing into InitialContext contain, for example, a PROVIDER_URL key instructing the lookup to happen on some distant foreign JNDI tree.
So, I would start by scrapping that parameter:
Context aContext = new InitialContext();
And then give it another shot.
If that still fails, use WebSphere's dumpNamespace utility to get a clear picture of WebSphere's JNDI tree.

I'm not sure what the ibm-web-bnd.xml does, however you could try two things.
First you can try doing a global lookup. Try:
aContext.lookup("jdbc/DB2DB");
I assume the datasource is named "jdbc/DB2DB" withing the datasource configuration.
Otherwise you should check if the datasource is mapped in your application. I guess the ibm-web-bnd.xml should when set up properly do that mapping.

Dump the namespace and find the jndi under target you want to find. If it is not found, update corbaloc URL to the one as given in the target. Because the look up was working in my local but not working in a clustered environment. I dumped the namespace and identified the corbaloc URL. Then used that corbaloc URL in the SIT environment.
Example: JMS_HOST was corbaloc::localhost:2809/NameServiceServerRoot in local but in clustered enviroment it was JMS_HOST=corbaloc::ABC-DEF-XYZ:9810/NameServiceServerRoot
This solved my issue.

Related

Binding datasource to application when using springBootApplication in Liberty?

When deploying "regular" web apps to Liberty, I was used to binding the global datasource configured in Liberty's server.xml to the individual application by using a child element within the element, like this:
<application context-root="helloApp" location="..." name="helloApp" type="war">
<application-bnd>
<data-source id="db2appDs" name="jdbc/datasource" binding-name="jdbc/theDB"/>
</application-bnd>
...
</application>
<dataSource id="db2ds" jndiName="jdbc/theDB" type="javax.sql.DataSource">
...
</dataSource>
When configuring my first Spring Boot application to deploy to Liberty, I am trying to use the new <springBootApplication> element for it - but I don't seem to be able to add a binding for the datasource I want to use the same way, as this element doesn't seem to support such a child. (It seems to want only <classloader> as a child).
I've seen people suggest I use an #Resource annotation that includes both application-local JDNI name and global JNDI name for the datasorce - but that defeats the purpose, since I don't want to know what the global name is until deploy time.
Is there another way to do this, like we used to before? Or are applications deployed through <springBootApplication> expected to know the global JNDI name of the datasource(s) they want?
Application-defined datasources are not supported for <springBootApplication/>’s. While your application may certainly access a Liberty datasource using its global JNDI name, you should configure the spring.datasource.jndi-name property within your Spring Boot application as described in section 29.1.3 of the Spring Boot features reference. For your example try spring.datasource.jndi-name=jdbc/theDB.

Adding ActiveMQ as a JMS Provider, Topic Connection Factory and Topic definitions

I am trying to add ActiveMQ as a JMS Provider in Websphere Application Server.
I have followed the instructions described here ActiveMQ 5.11 with WebSphere Application Server 8.5 and adapted to the topic.
Unfortunately I am not sure what I need to add in External JNDI name for both Topic Connection Factory and Topic definitions.
As per IBM documentation:
"External JNDI Name The JNDI name that is used to bind the queue into
the application server name space.
As a convention, use the fully qualified JNDI name; for example, in
the form jms/Name, where Name is the logical name of the resource.
This name is used to link the platform binding information. The
binding associates the resources defined by the deployment descriptor
of the module to the actual (physical) resources bound into JNDI by
the platform."
From my understanding this should be the name that I am using in my app to access the resource defined in WAS.
I also have added the resources in my deployment descriptor as resources.
Any help would be highly appreciated.
Regards
Given that you are accessing the resources via resource references (defined in your deployment descriptor), the configured JNDI name should match the lookup name that is defined in your resource reference.
For example, if your resource reference looks like this,
<resource-ref>
<res-ref-name>java:comp/env/jms/topicConnectionFactoryRef</res-ref-name>
<res-type>javax.jms.TopicConnectionFactory</res-type>
<lookup-name>jms/myTopicConnectionFactory</lookup-name>
</resource-ref>
or if your resource-ref lacks lookup-name and you instead have a ibm-web-bnd.xml file with a binding-name,
<resource-ref name="java:comp/env/jms/topicConnectionFactoryRef"
binding-name="jms/myTopicConnectionFactory">
</resource-ref>
then specify jms/myTopicConnectionFactory as the JNDI name.
Application code will then be able to do:
TopicConnectionFactory tcf = InitialContext.doLookup("java:comp/env/jms/topicConnectionFactoryRef");
Application code could also perform a direct lookup of the JNDI name as follows (although using the resource reference is preferred because it is more spec compliant and standard across app servers),
TopicConnectionFactory tcf = InitialContext.doLookup("jms/myTopicConnectionFactory");
The same applies to javax.jms.Topic.
If your resource environment reference in your deployment descriptor looks like this,
<resource-env-ref>
<resource-env-ref-name>java:comp/env/jms/topicRef</resource-env-ref-name>
<resource-env-ref-type>javax.jms.Topic</resource-env-ref-type>
<lookup-name>jms/myTopic</lookup-name>
</resource-env-ref>
or if your resource-ref lacks lookup-name and you instead have a ibm-web-bnd.xml file with a binding-name,
<resource-ref name="java:comp/env/jms/topicRef" binding-name="jms/myTopic">
</resource-ref>
then specify jms/myTopic as the JNDI name of the Topic.
Application code will then be able to do:
Topic topic = InitialContext.doLookup("java:comp/env/jms/topicRef");
Some optimizations/special cases:
If you have neither lookup-name nor binding-name, then WebSphere Application Server computes a default binding via the resource reference name. If this is the case for your resource reference, then you will have a deployment descriptor such as the following without any bindings file,
<resource-ref>
<res-ref-name>jms/myTopicConnectionFactory</res-ref-name>
<res-type>javax.jms.TopicConnectionFactory</res-type>
</resource-ref>
In the above case, specify jms/myTopicConnectionFactory as the JNDI name.
The application will be able to look it up as,
TopicConnectionFactory tcf = InitialContext.doLookup("java:comp/env/jms/myTopicConnectionFactory");

NonSqlTransientException in Liberty Server

am facing NonSqlTransientException Null userid not supported while starting the liberty server where my server.xml contain authdata
The authData configuration in Liberty is only for container managed authentication. If you are using application authentication (as is the case for JNDI lookup without resource reference, or if using a resource reference that is set to authentication type of Application), then authData does not apply. If you are using a resource reference with Container authentication, then you can use the authData, but there is an additional configuration step to associate the authData with the dataSource. This can be done in either of the following ways, documented in this knowledge center article.
One option is to configure the containerAuthDataRef of the dataSource to point at the id of the authData element (you'll need to add an id for it if it doesn't have one). Here is an example,
<authData id="myAuth" user="user1" password="pwd1"/>
<dataSource jndiName="jdbc/myDataSource" containerAuthDataRef="myAuth">
<jdbcDriver libraryRef=...
<properties...
</dataSource>
The other option is to specify the authData's id under the authentication-alias in the application's bindings (such as ibm-web-bnd.xml or ibm-ejb-jar-bnd.xml) for the data source. For example, the following bindings are based on the server config from the previous example,
<resource-ref name="java:app/env/jdbc/myDataSourceRef" binding-name="jdbc/myDataSource">
<authentication-alias name="myAuth"/>
</resource-ref>
It should be noted that the former is a default for container authentication that is used in the absence of the latter. So if you specify both ways, then the latter takes precedence and will be used instead.

Which JNDI datasource name works both on Wildfly and Websphere?

I've a java/spring web app that needs to be deployed as war file both on Wildfly and Websphere
The app is using datasource with JNDI names:
The WebConfig.java contains:
public DataSource dataSource() {
final JndiDataSourceLookup dsLookup = new JndiDataSourceLookup();
dsLookup.setResourceRef(true);
DataSource dataSource = dsLookup.getDataSource("jdbc/myDS");
return dataSource;
}
... and run perfectly on Websphere where JNDI datasource name is jdbc/myDS.
but Wildfly JNDI name has to start with 'java:/' or 'java:jboss/'
Changing WebConfig.java does the work:
DataSource dataSource = dsLookup.getDataSource("java:/myDS");
Which JNDI datasource name works both on Wildfly and Websphere (and maybe on others application servers?)
If you use resource references to do the lookup they would be relative to java:comp/env in both Liberty and Wildfly.
There are two ways to define a datasource. One is using the javax.annotation.Resource annotation. This can be used on a type, method, or field definition.
You can also do it in the web.xml or ejb-jar.xml using a resource-ref element:
<resource-ref>
<description />
<res-ref-name>myRef</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
If you are providing the userid/password in the application code then the res-auth element should contain Application
I was in the same situation (though I had an ejb-jar.xml).
On WebSphere we were asked to let the DataSource be bound to the right JNDI name manually at deploy-time, so in order for it to work, I declared the resource-ref like this:
[ ... ]
<session>
<ejb-name>MyEjb</ejb-name>
<resource-ref>
<description>DataSource</description>
<res-ref-name>java:comp/env/jdbc/myDatasource</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
</resource-ref>
[ other stuff... ]
</session>
[ ... ]
In the code, I would do the lookup like so:
(DataSource) InitialContext.doLookup("java:comp/env/jdbc/myDatasource");
Now, my boss wanted me to make it so that the same application could be deployed on WildFly where the DataSource's JNDI name would always be java:/myDatasource, and it had to work without adding checks in the code to use another lookup string (so, with just the same line I wrote above).
After a few hours, I had a working solution.
I added in the ejb's META-INF folder a jboss-ejb3.xml file in which I overrode that resource-ref like so:
[ ... ]
<session>
<ejb-name>MyEjb</ejb-name>
<resource-env-ref>
<description>DataSource</description>
<resource-env-ref-name>jdbc/myDatasource</resource-env-ref-name>
<resource-env-ref-type>javax.sql.DataSource</resource-env-ref-type>
<lookup-name>java:/myDatasource</lookup-name><!-- JNDI name of the DataSource -->
</resource-env-ref>
</session>
[ ... ]
Since the jboss-ejb3.xml file is ignored by WebSphere, the application could be deployed on both web servers.
Notice how I had to define the node as a resource-env-ref. The reason (by what I understood) is that resource references (not resource environment references) whose names start with "java:" aren't found in the java:comp/env "node". As such, I had to configure the DataSource's reference as a resource environment reference. The lookup-name node maps it to the correct JNDI name. This way it could be found by doing the lookup with the same string "java:comp/env/jdbc/myDatasource".
Here's the documentation about the jboss-ejb3.xml file.
One thing to take notice of: I encountered what is probably a bug in WildFly when I deployed my application after doing those changes in the ejb-jar.xml and adding the jboss-ejb3.xml file. The previous version of the application was already deployed, and when I replaced it the deployment failed with this error:
java.lang.IllegalArgumentException: WFLYEE0047: Incompatible conflicting binding at java:jboss/exported/MyApp/my-ejb/MyEjb!com.example.MyEjbRemote source: org.jboss.as.ejb3.deployment.processors.EjbJndiBindingsDeploymentUnitProcessor$2#65f33ac5
Stopping WildFly, clearing the "tmp" folder and re-starting it allowed my application to deploy.

Accessing JNDI from within Eclipse OSGI bundle, hosted in WebSphere App Server

I have a problem accessing JNDI resources from within an OSGI bundle, hosted in
WebSphere Application Server (WAS) using a servlet bridge.
It is failing on creating the JNDI initial context. My code is:
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
"com.ibm.websphere.naming.WsnInitialContextFactory");
InitialContext ctx = new InitialContext(env);
This fails with:
javax.naming.NoInitialContextException:
Failed to create InitialContext using factory specified in hashtable {java.naming.provider.url=corbaloc:rir:/NameServiceServerRoot, java.naming.factory.initial=com.ibm.websphere.naming.WsnInitialContextFactory, java.naming.factory.url.pkgs=com.ibm.ws.naming:com.ibm.ws.runtime:com.ibm.iscportal.jndi} [Root exception is java.lang.NullPointerException]
When I run the same code directly within a WAR module (not using OSGI), it is successful. I assume therefore the problem is something about accessing JNDI from within OSGI.
I have seen some references to Class Loader problems when accessing JNDI from within OSGI ... not sure if this is my problem, since the above exception does not explicitly relate to class loading, but maybe it is. Anyhow, if this is the problem, I am not sure how to fix it!
Is it in fact possible to access JNDI and JDBC entries set up within WAS, from within my OSGI module?
My application is an Eclipse RAP (Rich Ajax Plugin), packaged into a WAR file using the Eclipse WAR Product Tooling described at:
http://eclipsesource.com/blogs/2010/08/17/equinoxrap-war-deployment-an-end-to-the-pain/
This works successfully so far, apart from the JNDI access.
Many thanks
David
By default the thread context classloader will be used to load the InitialContextFactory. This is probably (but no guarantee) your bundle's classloader. You have a couple of options:
Configure the org.osgi.framework.bootdelegation property. This is probably implicitly set to sun.,com.sun. so you want to change it to be sun.,com.sun.,com.ibm.websphere.naming.* I believe this can be set in the servlet bridge wars WEB-INF/launch.ini
You could also import comibm.websphere.naming which would require you to add to the launch.ini org.osgi.framework.system.packages.extra=com.ibm.websphere.naming
Either should work.
Good luck.

Resources