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.
Related
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.
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");
I'm new to JPA and Liberty. Could anyone please explain how to relate/link the server.xml, web.xml and persistence.xml configuration to set up the database connection?
your help on this is much appreciated.
In Liberty, you define the location of the JDBC driver jar files and configure a dataSource element with a JNDI name. This knowledge center page contains an example for MySQL,
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_dep_configuring_ds.html
Directly quoting from the above page,
<dataSource id="DefaultDataSource" jndiName="jdbc/mySQL">
<jdbcDriver libraryRef="MySQLLib"/>
<properties databaseName="SAMPLEDB" serverName="localhost" portNumber="3306"/>
</dataSource>
<library id="MySQLLib">
<file name="C:/mysql-connector-java-x.x.xx/mysql-connector-java-x.x.xx.jar"/>
</library>
After this, you can configure the jta-data-source element in your persistence.xml pointing at the JNDI name that you chose. For example,
...
<persistence-unit name="ExamplePersistenceUnit">
<jta-data-source>jdbc/mySQL</jta-data-source>
</persistence-unit>
The above is sufficient to get it working, without involving web.xml.
The deployment descriptor (web.xml) gives you the option of adding a level of indirection/mapping and the ability to configure some additional settings such as shareability and container vs application authentication. You can do this by defining a resource reference in web.xml pointing to the data source. Resource references have names in java:comp/env, java:module/env, java:app/env or java:global/env that reflect their visibility. I'll use java:module in the following example, meaning that the reference we are defining is only visibility within the same module (the web module that provides the web.xml),
<resource-ref>
<res-ref-name>java:module/env/jdbc/mySQLRef</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
<lookup-name>jdbc/mySQL</lookup-name>
</resource-ref>
After defining the resource reference above, the data source continues to be available at the JNDI name specified in server.xml, but also becomes available via the JNDI name of the resource reference, meaning you could alternately specify,
<jta-data-source>java:module/env/jdbc/mySQLRef</jta-data-source>
Deployment descriptors can also do some more advanced things like defining a data source in place of the server config. However, to keep this answer simple, I've skipped over that possibility.
This IBM KnowledgeCenter topic is a good place to start
I'm using worklight 6.1 for my mobile app project. My problem is I got this error when trying to upload .war file into websphere in step 7 according to this documentation.
ADMA0007E: A Validation error occurred in task Mapping resource references to resources. The Java Naming and Directory Interface (JNDI) name is not specified for reference binding jdbc/WorklightDS in module Worklight with EJB name .
ADMA0007E: A Validation error occurred in task Mapping resource references to resources. The Java Naming and Directory Interface (JNDI) name is not specified for reference binding jdbc/WorklightReportsDS in module Worklight with EJB name .
I extract my .war file and open my web.xml. Then I got this details.
<resource-ref>
<description>Worklight Server Database</description>
<res-ref-name>jdbc/WorklightDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
<resource-ref>
<description>Reports Database</description>
<res-ref-name>jdbc/WorklightReportsDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
I had no idea regarding to this database. It's like reporting tools in worklight. Why it happen? Why?
The resource reference from your application doesn't match any resources defined in the websphere JNDI namespace. You have to define the connections to the database, give them a JNDI name and define them in the screen shown in your screenshot.
I already got the answer. I need to install worklight server first before deploy war file.
I am trying to get Spring working with tomcat JNDI resource to access my database. My project works if a META-INF/context.xml in my project with the resource information but once I remove it it stops.. why.
If you deploy a Web application in Tomcat, in the deployment process, Tomcat will copy the META-INF/context.xml file in $CATALINA_HOME/conf/ so the context will be available for your application. Take in mind, that if you remove context.xml from you application because you dont want it, you also have to delete it manually from $CATALINA_HOME/conf/
If you have edited the server.xml for including your dababase resource and is not working when you remove context.xml it could be because you made some mistake defining your resourde in server.xml
UPDATED:
When resource is in server.xml, in context you should make a reference to global resource in server.xml. For example:
<Context crossContext="true" reloadable="true" >
<ResourceLink name="jdbc/myApp" type="javax.sql.DataSource" global="jdbc/myApp" />
</Context>
This is unrelated to Spring.
To use JNDI you are expected to define the various resources either as global configuration or as application specifici configuration. For example JNDI DataSource Configuration
Why do you expect it to work in any other case? How would Tomcat know which resources to provide if you don't define them?
UPDATE:
You define a resouce in your server.xml but you have to associate the resource with your web application. That is why you also need to modify context.xml