I got a legacy EJB 2 application which I deploy to Websphere 8.5. The application has dependencies, which define JNDI bindings to a DataSource in /META-INF/ejb-jar.xml and /META-INF/ibm-ejb-jar-bnd.xml.
I'm not allowed to change the code in those dependencies and neither can I change the Websphere's config. But I could make changes to the config files in the jar files.
I want to override the effective JNDI bindings in my application. Is it possible to define a file that will be added to the Ear to override those bindings?
snippet of the ejb-jar.xml:
<resource-ref id="ResourceRef_1248968390265">
<res-ref-name>jdbc/CentralDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
ibm-ejb-jar-bnd.xml:
<session name="FooJob">
<resource-ref name="jdbc/CentralDS" binding-name="jdbc/VeryCentralDs" />
</session>
Is it possible to override this JNDI name (VeryCentralDs) somewhere?
Yes, it is possible to override resource reference bindings at deployment time. This knowledge center article steps through deploying an application. Watch for the step "Map resource references to resources" which is documented here. This is where you can fill in the target JNDI name that you want the resource reference bound to.
Related
We have an EJB application with a jboss-ejb3.xml which defines resource-refs for JNDI mapped resources. In our use-case not all resources are available in all environments. Since jboss-ejb3.xml cannot be externalized, I was hoping if there was a way the definitions can be somehow marked optional so the deployment does not fail when a mapped resource is not configured?
For example, we have our jboss-ejb3.xml defined as:
<resource-ref>
<res-ref-name>cache/ErrorDataCache</res-ref-name>
<res-type>java.util.Map</res-type>
<jndi-name>java:jboss/infinispan/cache/ejb/ErrorDataCache</jndi-name>
<!-- what to add to make this optional ?? -->
</resource-ref>
In our DEV JBOSS EAP 7.2 server, we are configuring a back-end cache so when server starts up and deploys the application, it registers the JNDI context (java:comp/env/cache/ErrorDataCache) to the mapped resource (java:jboss/infinispan/cache/ejb/ErrorDataCache).
However, in our production servers of same EAP version, we are forbidden to cache these values. Also we are forbidden to change the EAR archive to maintain a separate jboss-ejb3.xml.
I also tried using system properties substitution/placeholder, but there has to be a default fall-back otherwise it still fails with error "unresolved property value of app.module.env.${mappedjndi.errordatacache}"
<resource-ref>
<res-ref-name>cache/ErrorDataCache</res-ref-name>
<res-type>java.util.Map</res-type>
<jndi-name>${mappedjndi.errordatacache:"what default value??"}</jndi-name>
</resource-ref>
I have read that there is an <ignore-dependency/> tag which I tried, but it fails with error: invalid tag , not defined in the XSD.
When using Tomcat, I've always treated web.xml as a kind of .htaccess or httpd.conf equivalent. It seems natural that there might have to be some way of configuring a web server.
However, I don't quite understand the purpose of context.xml. For instance, when working with JDBC, why do I have to add a resource-ref in web.xml and also a Resource with even more info in context.xml? Could I eliminate the context.xml file and somehow instantiate the DataSource in my code? I am asking because hypothetical examples like that help me understand.
EDIT: I am trying to understand what is happening in configs like this, in /META-INF/context.xml:
<Context>
<Resource name="jdbc/postgres" auth="Container" type="javax.sql.DataSource"
driverClassName="org.postgresql.Driver" url="jdbc:postgresql://127.0.0.1:5432"
username="postgres" password="yes" maxActive="20" maxIdle="10"
maxWait="-1" />
</Context>
and, in WEB-INF/web.xml:
<resource-ref>
<description>postgreSQL Datasource example</description>
<res-ref-name>jdbc/postgres</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Container</res-auth>
</resource-ref>
Why do I have to put both of those in there to use JDBC? What are they doing exactly and is there another way of doing the same thing but in the Java code? Like I said, not because I want to, but because I want to understand what they are doing better.
I don't quite understand the purpose of context.xml
context.xml is called from the web.xml through <context-param> tag. As you web.xml loads first when an application is created and it will create the references for the contexts that are configured in it.
I don't quite understand the purpose of context.xml
So, the purpose of context.xml is adding separation of codes. you can have separate contexts for different purposes . for example For Database connectivity, using other frameworks etc..,
Could I eliminate the context.xml file and somehow instantiate the DataSource in my code?
Yes ,you can do that by configuring the datasource in web.xml itself.
Hope this helps !!
To your initial questions:
I don't quite understand the purpose of context.xml
In Tomcat, you'll frequently see the term "Context". When you see this it's just referring to your application (i.e. Context == your web app). Thus /META-INF/context.xml is the configuration file specific to your application (actually, it's one of the configuration files because there are others).
For instance, when working with JDBC, why do I have to add a resource-ref in web.xml and also a Resource with even more info in context.xml?
You don't. You do not need to add anything to web.xml. If you define the resource in /META-INF/context.xml, Tomcat will create your resource and expose it through JNDI. You can then retrieve it as you would any resource from JNDI.
Could I eliminate the context.xml file and somehow instantiate the DataSource in my code?
Possibly. It's common to see Spring users create a DataSource in their Spring bean definitions. If you're not using Spring, you could still do it, but it would be more work.
Regardless of how you do this, if you setup the DataSource in your application you lose some flexibility. For example, you cannot share the DataSource across multiple applications and your application has to know how to set up the DataSource. If you define the DataSource in the server's configuration (i.e. with a Resource tag) then your application does not need this information.
To the response by san krish:
So, the purpose of context.xml is adding separation of codes. you can have separate contexts for different purposes . for example For Database connectivity, using other frameworks etc..,
The purpose of the Context tag is to configure the context (i.e. your application). It might provide you with the ability to pull certain aspects of your application, like the DataSource, out of the code and into configuration, but that's just the benefit of externalizing your configuration. It's not the purpose of this file.
Yes ,you can do that by configuring the datasource in web.xml itself.
No, with Tomcat you cannot configure a DataSource strictly through web.xml. It's just not possible to provide all of the information in web.xml that is required to create a DataSource. Because of this, you need to define a Resource tag for your DataSource and it is redundant to specify your DataSource in web.xml.
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" />
I developed a sample web application which will read the data from an external properties file. The properties file is in the source folder in my system and is not included inside the WAR file.
The property file is accessed like this:
Properties prop = new Properties();
//File f1 = new File("Property.properties");
prop.load(getClass().getClassLoader().getResourceAsStream("Property.properties"));
How do I access this property file externally inside the WAR file?
What changes have to be made in the code to read it in the WAR file?
I think the most versatile approach is to define a simple environment entry as described in the section EE.5.4 Simple Environment Entries of Java™ Platform, Enterprise Edition (Java EE) Specification, v5.
From the section (page 68):
A simple environment entry is a configuration parameter used to
customize an application component’s business logic. The environment
entry values may be one of the following Java types: String,
Character, Byte, Short, Integer, Long, Boolean, Double, and Float.
You may also use URL connection factory as described in the section EE.5.6.1.4 Standard Resource Manager Connection Factory Types of the specification.
The Application Component Provider must use the java.net.URL resource
manager connection factory type for obtaining URL connections.
Both require a definition of a resource reference in the deployment descriptor WEB-INF/web.xml of your web application so you can inject the value using #Resource or use JNDI API with java:comp/env as the entry point.
The benefit is that you can change the configuration of your web application without having to recompile the code as well as let you change it using an application server's administrative tools your admins are accustomed with.
In web.xml you define the resource reference.
<resource-ref>
<res-ref-name>propertiesURL</res-ref-name>
<res-type>java.net.URL</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
<resource-ref>
<res-ref-name>propertiesPath</res-ref-name>
<res-type>java.lang.String</res-type>
<res-auth>Container</res-auth>
<res-sharing-scope>Shareable</res-sharing-scope>
</resource-ref>
Then in your code you use the following to access the values:
#Resource
String propertiesPath;
#Resource
URL propertiesURL;
With this you met the requirements of Java EE and you can use propertiesPath or propertiesURL as if they were passed as input parameters to your methods.
Now, it's time to meet expectations of WebSphere Application Server.
What you defined are logical names that need to be mapped to their administered names (an application server knows about and can provide to the application).
In WebSphere Application Server you use WebSphere Binding descriptor WEB-INF/ibm-web-bnd.xml with the following configuration:
<?xml version="1.0" encoding="UTF-8"?>
<web-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-web-bnd_1_1.xsd"
version="1.1">
<virtual-host name="default_host" />
<resource-ref name="propertyURL" binding-name="propertyURL" />
<resource-ref name="propertyURL" binding-name="propertyURL" />
</web-bnd>
When the application gets deployed WAS allows you to map these mappings to its administered resources. Use the ISC console to define values of the environment entries and map them to the application.
It has became easier with WebSphere Liberty Profile. I described the mechanism as offered by WLP in my article Using #Resource to access JNDI in WebSphere AS 8.5 Liberty Profile.
You have three options:
configure the Websphere to include the directory which contains the property file in the classpath. Don't know how to do it, but I'm sure it is possible, since our application does the same thing
include the property file in the war archive. You probably don't want to do that.
instead using the classloader to load the property file use the file api with an absolute path. I'm not completely sure WAS does allow that, but it is a bad idea anyway, because it makes your application very dependent on things that it really shouldn't care about, such as the installation path of your application.
WebSphere has two folders on the classpath, properties can be loaded from there:
Enterprise Applications > myear > Manage Modules > myjar.jar > Class loader viewer
4 - Extension - com.ibm.ws.bootstrap.ExtClassLoader
file:/projekte/IBM/WebSphere/AppServer-8.5/classes/
file:/projekte/IBM/WebSphere/AppServer-8.5/lib/
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