Tomcat 7 Class Load preference order - java

I've got the following scenario:
On the one hand, I've got a tomcat instance with a lot of applications that need the activemq-all.jar which contains slf4j libraries, so I've deployed it into the lib directory, it is not optional for me to include this jar file on each app.
On the other hand I need to install a monitor application which I can't control and ships with a different version of slf4j.
Running the last application on another tomcat instance is also not an option.
I would like to configure tomcat's ClassLoader to try and load first the jars on the webapps and then the jars on the lib/ directory.
Is this possible? How can be achieved?

By Default tomcat loads the web app classes first and gives them a higher preference than classes in its own lib directory. You can keep the mentioned jar is the lb folder. Typically i would recommend the catalina_base directory

Load the common jars under the Common class loader. By default, the common class loader looks for jars under:
$CATALINA_BASE/lib
$CATALINA_HOME/lib
Any jars packaged with you web app should take precedence over those found in the Common class loader.

Related

Tomcat 8.x not loading custom jar from 'lib' folder

Background-I am trying to deploy a custom jar to the Tomcat 8.x lib("${catalina.home}/lib") folder. Per Tomcat documentation, it should be picked up when the server starts(via common classloader), and classes(from the jar) are made available to Tomcat and other apps deployed on it. However, I have an app deployed on Tomcat which is looking for the classes from this jar, but it fails with NoClassDef found error.
What I have done so far- I have tried to look at the classes deployed by using -verbose:class but am unable to find the class(es) from the jar. It appears that tomcat ignored the custom jar(yes- I understand all the classes are not loaded at the startup rather they can be 'found' using delegation pattern at runtime). To test that tomcat is working per documentation ie autoload from 'lib' folder, I threw in the ojdbc.jar in the same lib folder. Voila- I could see it loading some classes from the ojdbc jar(at this stage,my code doesn't need ojdbc.jar or classes from it).
Need help -- I am unable to understand why tomcat is ignoring my custom jar, while it deploys ojdbc.jar(at a theoretical level it is also custom as it is not bundled with tomcat) ?

How to do shared library in tomcat version 6.0 in Linux environment?

I have a two application webapp1 and webapp2. Both application use the same library zx.jar.
Now i have put the jar in two location /webapp1/ROOT/WEB-INF/lib and /webapp2/ROOT/WEB-INF/lib
But I don't want to load jar twice. I want to use the jar /tomcat/lib ?
How can I implement this in Linux environment?
Put your library at below location
•Tomcat 6 $CATALINA_HOME/lib
•Tomcat 5 $CATALINA_HOME/common/lib
More info Apache ClassLoader Howto.
Just put your jar in the in the tomcat lib folder ($CATALINA_HOME/lib).
And if you are using maven as build tool, just put <scope>provided</scope> in the dependency of the corresponding jar!
And if you are using Ant to build, just make sure that, you don't copy the jar to the deployed application's lib folder, while building and deploying your application.
With Tomcat 6, "common" JARs to be shared between multiple servlets should be placed in $CATALINA_BASE/lib or $CATALINA_HOME/lib. It is documented in the Apache 6 - Classloader HOW TO document.
However you need to be careful when you do this because:
"common" JARS and other files / directories in the lib directories take precedence over stuff in each webapp,
any static variables in "common" classes are actually visible to all webapps, and
leakage of types from one webapp to another can cause strange problems; e.g. type casts failing unexpectedly.

How hard is it to load JARs from another location?

I have the following scenario. I'm working with a server which has a lib folder which contains all of its JARs, but things get kind of complicated when having multiple applications for the server, as the lib directory gets kind of crazy.
What I'd like to do is put all of my application's JARs in a different location and instruct the classloader to load them when my application is loaded. How can I do this? How will I need to rewrite my application to facilitate this?
As far as I know, it is not possible to load the jar files or set the CLASSPATH at runtime unless you have written your own class loader. Tomcat is a good illustration in which the tomcat's class loader loads the jar files dynamically in multi-level.
http://tomcat.apache.org/tomcat-6.0-doc/class-loader-howto.html
There is a common class loader which allow the jar files to be shared accross all web application. However, if you want to addthe jar files which are only loaded for the web application then you should add it under webroot, e.g. WEB-INF/lib. The libraries in this folder are not shared to all applications. For example, this means if two web applications are using different versions of the same library, they will not be mixed up.
Since I am using maven to manage the project, I do not need to worry about where to put my ja dependencies. Maven automatically bundles the libraries into war file for me.
So if you are not using servlet container, e.g. tomcat, jetty, etc. , then you will need to write a class loader. If that is necessary, then have a look into tomcat but it may not be easy.
You can add directories to the class path in Java 6.

eclipse tomcat why does it keep copying the servlet api jar

I am using eclipse and added tomcat 6 server. whenever i try to start the server it automatically copies the server api jar into the WEBINF/lib folder and the app does not start
INFO: validateJarFile(/media/01CB9CAC704E03A0/Projects/.metadata/.plugins/org.eclipse.wst.server.core/tmp1/wtpwebapps/myapp/WEB-INF/lib/servlet-api-2.5.jar) - jar not loaded. See Servlet Spec 2.3, section 9.7.2. Offending class: javax/servlet/Servlet.class
I got the same problem and finally got it to work after looking at this among other pages. I am going to list it here in case other people run into the same issue.
In my case, the myeclipse project was created from a maven .pom file which lists the JEE 1.5 files as "provided" scope i.e. these files will be provided by the container (in my case tomcat 6). So if I create a war file using maven and drop it in the webapps dir it just works fine. It gets a little tedious doing that every time you make a change, so I decided to go for exploded deployment and thats when I ran into the same issue.
Since the project file was created from the pom file, these dependencies came in but Eclipse project file does not recognise these as "provided" and not to be deployed. And TOMCAT is not happy when it finds two implementations of the spec:
"Servlet spec 2.3 sec 9.7.2 recommends … The classloader that a container uses to load a servlet in a WAR must allow the developer to load any resources contained in library JARs within the WAR following normal J2SE semantics using getResource. It must not allow the WAR to override J2SE or Java servlet API classes. It is further recommended that the loader not allow servlets in the WAR access to the web container’s implementation classes. It is recommended also that the application class loader be implemented so that classes and resources packaged within the WAR are loaded in preference to classes and resources residing in container-wide library JARs."
I toyed with the above solution to change my deplyment assembly config but that is not helpful alone since these jars get bundled in if I select the "JARS from the build path"
in the menu project properties/MyEclipse/Web/Deplyment/Configure workspace settings.
And I need to do that cos I have other dependencies jars (not provided by container).
Solution:
I removed these jars from the dependencies in the build path manually.
Instead I added a dependency on User Library - JAVA EE5.
And in the deployment configuration I removed the option of JARS exported from User Libraries of required projects.
YMMV. But in any case if you read the servlet spec definition above and then look at the config in your workspace, you can sort it out.
Hope this helps.
Go to your project properties and look under Deployment Assembly page. This page describes how your app will be packaged for deployment or export. Take a look at entries regarding libraries. You have to figure out which of those entries points to the servlet api jar and remove it. If the entry points to other jars that do need to be packaged, you will need to split it into several separate build path entries, so you can tell Eclipse exactly what does and does not need to be packaged.

How do you configure JBOSS to use the xml lib in the web app?

JBOSS is throwing a:
java.lang.NoSuchMethodError: org.w3c.dom.Document.getDocumentURI()Ljava/lang/String;
Error when loading a wsdl. Can I configure it to prefer the library in my WAR instead of the system or app server lib?
The app server should already be using any JARs in WEB-INF/lib, along with the system and app server library paths - the standard approach to this is that the ClassLoader for WEB-INF/lib delegates class loading to the app server lib, which delegates class loading to the server lib, and only if the parent classloader cannot find the class does it attempt to load it's own classes.
In other words, if you place the same class in WEB-INF/lib and the app server's lib, the latter JAR will always be used. This means it is possible to create conflicts by having classes with the same names but different versions available in both WEB-INF/lib and the app server's lib - are you sure this isn't what's causing your issues? Can you resolve the conflict?
Some app servers (not sure about JBoss, but I know WebSphere allows it) lets you configure the classloader so that the child loader is checked first (child-first vs parent-first), but this type of configuration can cause other issues.

Categories