sgargel
sgargel

Reputation: 1046

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?)

Upvotes: 4

Views: 2439

Answers (2)

nonzaprej
nonzaprej

Reputation: 1600

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.

Upvotes: 0

Alasdair
Alasdair

Reputation: 3176

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

Upvotes: 0

Related Questions