Reputation: 1046
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
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
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