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) ?
Related
I have a spring boot application using ms-sql database, it deploys properly in external tomcat when the server is newly started, but when I redeploy the same war file I get the following error(the war file still deploys but is not functioning properly:
Native library mssql-jdbc_auth-8.4.1.x64.dll already loaded in another classloader when I redeploy the war file in external tomcat.
So I undeploy the war file, restart the tomcat server, and redeploy it, and it's deploying properly and working (functions and CRUD).
I am using tomcat 9.0.43 and there are no other applications deployed to the server instance.
EDIT: I am running tomcat on windows and also have the .dll file in the tomcat bin folder. Also I'm using maven for dependency management.
The program uses integrated security for DB auth
Your problem comes from the double usage you want to make of your WAR file:
on one side you need the JDBC driver whenever you run the WAR file using java -jar,
on the other side you don't want JDBC drivers in the web application's classloader, whenever the WAR file is deployed in a servlet container. The servlet container should provide the drivers.
Fortunately the spring-boot-maven-plugin already provides such a feature in the repackage goal: all the dependencies marked as provided (such as the Embedded Tomcat libraries) are placed in the WEB-INF/lib-provided folder and hence are not loaded by the servlet container.
Therefore you only need to mark the JDBC driver as provided and add it to Tomcat's common loader's classpath ($CATALINA_BASE/lib).
I have two WAR files that i need to deploy on a server.
the catch is that i cant run another tomcat on that server.
deploying two WAR files is easy but, is it possible to run them both while one of them uses
Spring 3.8
and the other one uses
Spring 4.1.4
which is the latest version?
Will it conflict?
answers like "try it out" are acceptable :) but i need to know for sure so i wont have issues in the future.
Thanks
See the following for an explanation of how Tomcat's classloading mechanism works:
http://tomcat.apache.org/tomcat-7.0-doc/class-loader-howto.html
WebappX — A class loader is created for each web application that is
deployed in a single Tomcat instance. All unpacked classes and
resources in the /WEB-INF/classes directory of your web application,
plus classes and resources in JAR files under the /WEB-INF/lib
directory of your web application, are made visible to this web
application, but not to other ones.
If, then, the Spring Jar files are bundled in WEB-INF/lib for each application then you will have no issues. An issue would only arise if they were in some shared location.
two different application under tomcat has two diffferent classpath and classloader so they don't conflict
latest as of today is 4.2.0 (under dev), you can keep track at http://projects.spring.io/spring-framework/
I have a Spring webapp running in Glassfish 3.1.2. I am just beginning to convert the webapp to OSGi. I undeployed the existing webapp and copied the spring and gemini OSGi jars into the modules directory in the Glassfish installation. I then installed and activated them using the Glassfish OSGi web console (which I understand to be some sort of customised Felix web console) and everything was fine. It didn't do anything but I could install and activate them in the web console which is what I wanted to test.
I then started to redeploy the non-OSGi jars of my existing webapp using the Glassfish Application console to see if the 2 type of jars could coexist, which, given my understanding of OSGi I thought they should be able to. At this point NoClassDefFoundErrors started getting thrown complaining about not being able to find org.apache.commons.logging amongst other classes. These class were present in both the Module directory as the installed OSGi jars and the application classpath. I then deactivated the jars in the console but didn't remove the the OSGi jars but the exceptions continued to be thrown.
I got a classloader print out and found that the jars in the WEB-INF of my webapp weren't getting loaded but I wasn't sure whether this was the problem or a symptom.
I then removed the jars from the uninstalled the OSGi jars and everything started working again and the webapp could be deployed.
Can anyone think of any reason why this might happen? I am guessing that the content of the module directory is on the classpath but if so why? How would I prevent this from causing problems if I want OSGi and non-OSGi jars to work together?
Side Notes
When I viewed the classes getting loaded by the classloader I couldn't see content form the modules folder getting loaded.
I can install and activate the OSGi jars after the the non-OSGi jars are deployed but not the other way round.
( Disclaimer: I do not have specific experience with glassfish, but JBoss and other
strange environments sporting classloader hierarchies)
You have to be carefull with classloader hierarchies in java - the same bytecode equal class will not be equal or asignable to if comes from another classloader, and while loading classes it is important to find dependencies through loading classloader or his parents.
To resolve your situation you will have to carefully examine this hierarchy and check settings for delegation and class resolution ( like parent first / self first ).
JBoss tried to solve this problem by introducing unified classloader which resulted in one big pile of assorted classes and leaks of resources between contexts / webapps in default setting.
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.
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.