JNDI configuration in Tomcat - java

I am trying to set up JNDI lookup in web application to be deployed in Tomcat 7. I have specified following properties in jndi.properties file:
java.naming.factory.initial=org.jnp.interfaces.NamingContextFactory,
java.naming.factory.url.pkgs=org.jboss.naming:org.jnp.interfaces,
java.naming.provider.url=localhost:1199
But when i get initial context and inspecting its attributes it reveals that java.naming.factory.initial changes to org.apache.naming.java.JavaURLContextFactory and all other properties remains same as in the jndi.properties file.I dont understand why this single property gets changes ? How can i prevent this and force tomcat to use property i have specified ?

I believe the JNDI properties should be vendor specific, What you trying to put is for Jboss JNDI properties, and may have been reverting to for Tomcat Specific Proerties. Although you can try to overwrite them programatically, it might not work properly.

You should put all this stuff into a Resource element in your META-INF/context.xml file, and look up that resource via a java:comp/env URL. That's what Tomcat is trying to set up here: an object factory for that namespace.

I think you should append your properties to your catalina.properties file,it's under your $tomcat_home/conf.

Related

Store properties in database, but override locally

Currently, we store our application's environment properties in a .properties file in the WEB-INF. We want to move them to a database table. But we still want to specify the jndi name, and when running in our test environment locally, we want to be able to override certain properties just for our workspace for test and development.
Apache commons' DatabaseConfigurator seemed nice, but wouldn't play nice with the jndi name being defined as a property in the file. Nothing I did to ask it to look at the property file first worked.
I decided to subclass apache commons' AbstractConfiguration to try to create a single configurator that would check the file and database as I wished, but again, it didn't really work. Spring wants that jndi name absolutely first, probably because the data source has to be passed into the configurator as a parameter.
How can I get what I am after here? Mostly properties in the database, but those that are in the file override them. And jndi name for the datasource should not have to be hardcoded in the spring config.
Why don't you write a ApplicationContext listener that will read the configuration from your DB and inject them in the JNDI? Then you can override the configuration in the JNDI with a context.xml file that will be placed in the src/local/webapp/META-INF/.
This is how we get this working in our webapp.

com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Invalid resource

I'm trying to figure out where is the definition of the above resources stored. My application does not have and never had such resource defined. So I'm actually sure this is some kind of server reference but the question is where such stuff could be defined. It looks for me like some kind of cached references existing somewhere on the server and used when the same names are tried.
People advice workarounds like creating resources manually or using java:app/ prefix.
However I'd like to go tot the bottom of the problem and resolve the source of the problem instead.
The contain entity manager config could be the first thing to check but where is it?
What config file should I examine, modify or remove.
Here is the beginning of the error message:
Severe: Exception while preparing the app : Invalid resource : jdbc/CustomerDEV1__nontx
com.sun.appserv.connectors.internal.api.ConnectorRuntimeException: Invalid resource : jdbc/CustomerDEV1__nontx
To get rid of it, you´ll need to remove the persistence.xml cached by the IDE. For example (using Netbeans 8 under Windows 8.1):
C:\Users\jMarcel\AppData\Local\NetBeans\Cache\8.0\index\s71\java\14\classes\META-INF\persistence.xml
Hint: in WindowsExplorer, set your directory to C:\Users\yourUser**AppData\Local\NetBeans** and perform a search for the persistence.xml file.
I hope you are not letting the server know what type of resource you are looking up in the JNDI tree and confusing it. You look for JDBC resource in within application. Please note that if you use java:app/ then it means
The java:app namespace is used to look up local enterprise beans packaged within the same application. That is, the enterprise bean is packaged within an EAR file containing multiple Java EE modules. JNDI addresses using the java:app namespace are of the following form:
You have to use java:comp/env/jdbc/CustomerDEV1__nontx for JDBC Datasource. java:comp/env/jdbc denotes it is a JDBC resource in the Java components environment

Optional JNDI Binding For Websphere Web Application

I would like to have optionally supplied information available to my webapp when deployed to Websphere (we are using 8.5) via the application's JNDI context.
I know that I can put a resource-ref or resource-env-ref in my web.xml but when I do that WAS will require me to supply a binding for it and deployment time.
My application will look in JNDI for certain values and adjust its behavior if found, but will function fine with default behaviour if it does not find values in JNDI. How, in WAS, do I supply a binding (just for a string or a URL) for my webapp without declaring a dependency on it in a resource-ref or resource-env-ref in my web.xml.
I know how to do this in Tomcat, I just put a Environment entry in the context.xml, like this:
<Environment
name="com.myorg.config"
value="http://localhost:8081/suff"
type="java.lang.String"/>
You can use an #Resource String lookupName; to accomplish the same in a portable manner. You will be prompted for a value at deployment time, but you can specify nothing, which will cause no value to be injected.

Why is Realm setting required in Server.xml and not web.xml

I am working on a Java application for a while. I primarily work on .NET Platform. Although I feel lot of concepts are common between these two platforms but there are few areas where I am finding some issues related to the configuration.
I am working on Authentication and Authorization and thought I would get something similar to Membership APIs of .NET in JAVA. Closest which I got was using j_security_check. I also got to know about JAAS but think it is little too deep for me to dive into.
I have created the user and role tables in the database and now I have to specify the JDBC Realm settings somewhere. I am using Tomcat 7.0. In most places, it's mentioned that I need to specify the realm setting in the server.xml.But wouldn't that apply to all web application deployed on that server since it would become a server level configuration ?.
On a site I even saw a developer mentioning about context.xml but again can't see a standard document that mention about using this XML file for setting JDBC realm
In.NET, We always put Membership settings at the web.config level and not Machine.config.
Totally Confused on this. Looking for some light on this.
Why is Realm setting required in Server.xml and not web.xml
This is not true, you can define it in your webapp as well, but then only in a servletcontainer-specific configuration file, such as /META-INF/context.xml in case of Tomcat. It cannot be definied in /WEB-INF/web.xml because it's specific to the standard Servlet API, not the servletcontainer implementation.
But wouldn't that apply to all web application deployed on that server since it would become a server level configuration ?.
That's correct. This is not recommended if you have no control over the server or if you don't want to publish the realm through other webapps.
On a site I even saw a developer mentioning about context.xml but again can't see a standard document that mention about using this XML file for setting JDBC realm
You can specify it in webapp's /META-INF/context.xml. See also Tomcat's own documentation on the <Context> element:
Defining a context
It is NOT recommended to place <Context> elements directly in the server.xml file. This is because it makes modifying the Context configuration more invasive since the main conf/server.xml file cannot be reloaded without restarting Tomcat.
Individual Context elements may be explicitly defined:
In an individual file at /META-INF/context.xml inside the application files. Optionally (based on the Host's copyXML attribute) this may be copied to $CATALINA_BASE/conf/[enginename]/[hostname]/ and renamed to application's base file name plus a ".xml" extension.
In individual files (with a ".xml" extension) in the $CATALINA_BASE/conf/[enginename]/[hostname]/ directory. The context path and version will be derived from the base name of the file (the file name less the .xml extension). This file will always take precedence over any context.xml file packaged in the web application's META-INF directory.
Inside a Host element in the main conf/server.xml.
(emphasis is not mine, it is already as such in Tomcat's documentation)

Using a JNDI datasource created by another application with Tomcat

I have a .properties file in my application which contains dataSource properties.
I set up a JNDI reference to this dataSource using the following code :
// first I create MyDataSource from the properties found in the .properties file
//then :
Context initContext = new InitialContext();
initContext.createSubcontext("jdbc");
initContext.createSubcontext("jdbc/oracle");
initContext.rebind(jdbc/oracle/myDataSource, MyDataSource);
If I use a lookup in this application, the dataSource is found :
Context initContext = new InitialContext();
BasicDataSource dataSource =
(BasicDataSource) initContext.lookup("jdbc/oracle/myDataSource")
//everything works fine and I can use my dataSource to getConnection,
//requests, etc...
Now I would like to use this dataSource in another application. But if I do the same lookup than previously, I don't find myDataSource (whereas there is still the previous application in tomcat and the jndi binding is done on start-up with the help of a listener).
How can I get myDataSource in this second application, given that I can't use a Tomcat's resource in server.xml or a context.xml file (for different reasons I have to use this .properties file)?
Thanks
"local" JDNI directories are read-only in Tomcat. Nevertheless, you can bind "global" JNDI resources in a LifecycleListener, and then "link" them to your context(s)(*):
You need to implement org.apache.catalina.LifecycleListener http://tomcat.apache.org/tomcat-6.0-doc/api/org/apache/catalina/LifecycleListener.html
Then register it in your server.xml like this (along with the other listeners):
<Listener className="yourlistener.YourLifecycleListener"/>
Your listener should await for 2 events:
public void lifecycleEvent(final LifecycleEvent event) {
if (Lifecycle.START_EVENT.equals(event.getType())) {
// Create your datasource instance...
Context initContext = new InitialContext();
initContext.createSubcontext("jdbc");
initContext.createSubcontext("jdbc/oracle");
initContext.rebind("jdbc/oracle/myDataSource", myDataSource);
} else if (Lifecycle.STOP_EVENT.equals(event.getType())) {
// unbind...
}
}
Then you'll have to propagate resource accesses by "linking" them from "global" JNDI directory to "local" JNDI directory using ResourceLink element in your META-INF/context.xml:
<ResourceLink name="jdbc/oracle/myDataSource" global="jdbc/oracle/myDataSource"
type="javax.sql.DataSource" />
That worked for me so far.
(*) Some notes:
There's an advantage on using lifecycle listeners. Since the order of context creation is not guaranteed. The advantage is that all of your contexts will see this object created.
If you need to create and configure datasource creation more dynamically that on lifecycle listener creation, note that you can bind a custom class implementing the Factory pattern.
To avoid classloading incompatibility problems, consider putting your listener, datasource, etc. classes in a jar file in the Tomcat lib directory, so they're included y the common classloader.
Regards.
What you are trying to do is not going to work. J2EE applications are not allowed to modify the JNDI environment provided by the application server (J2EE spec, section 5.2.2) and the Tomcat JNDI documentation also states, that each web applications gets each own read-only JNDI environment. I'm not sure why binding/rebinding your datasource is not failing immediately and why it's working within the same web application, but even such application-internal usage of the JNDI environment is undocumented behaviour, which I would not rely on.
A couple people have already commented on this, but I think the answer to your question is: Tomcat has a file called server.xml that you need to use. A good reference I have used before is below:
http://tomcat.apache.org/tomcat-5.5-doc/jndi-resources-howto.html
Resources defined here will be visible to all apps deployed (if set up correctly). If you set up a JNDI resource in your apps context or web xml file, it should only be available to your app.
JNDI context are private to each webapp. Context created in one app can't be accessed by others.
Try to create an entry in GlobalNamingResources and links in both webapps using <ResourceLink> to see if it works.
I used this setup before to read from both apps but never tried to write from one. So not sure if it will work.
Actually, it is possible to access others JNDI resources, if the servlet implements org.apache.catalina.ContainerServlet. This interface has a org.apache.catalina.Wrapper attribute, that is "populated" by the container itself.
through that, I created a simple application to monitor resources.
BUT, I would like to do that in a listener, so my resource monitor could start when the container starts. Anyone knows a way?

Categories

Resources