I was recently trying to solve class cast exception in our web application. After few tests have found out that the classloader information for our web application right after application server restart are different from classloader information after webapp restart/update (without app server restart).
Classloader information were retrieved using the Manage modules - View Module class loader - Export in the Websphere administration console.
The items (paths to webapp .jar files) in exported XML are the same. But some of the items (as I understand it - these are the classes in webapps' classloader) are different.
Could anybody explain why?
Thanks.
Update:
Here is the difference which is maybe the main problem (I keep getting ClassCastException on XMLSignatureFactory in my log file). This class is contained in xmlsec library and this library is deployed with our webapp war file. The classloader order is set to PARENT LAST, but it seems like sometimes the XMLSignatureFactory from IBM JDK is loaded instead of the xmlsec implementation (after redeploy).
I have described the exception further in this post. After I have changed the settings in MANIFEST.MF file and set up the servlet listener, I could get the application working after every restart, but the redeploy problem still occurs (which is quite annoying).
I got the same problem here. To fix that issue, push xmlsec jar to AppServer\classes then we can override IBM JDK by our lib
Related
I developer a web application using Java. When I deploy it to my application server (Jetty, Tomcat, JBoss, GlassFish, etc.) throws an error. I can see this error message in the stacktrace:
java.lang.ClassNotFoundException
Or
java.lang.NoClassDefFoundError
What does this mean and how can I fix it?
What does this mean?
First, let's see the meaning of java.lang.ClassNotFoundException:
Thrown when an application tries to load in a class through its string name using:
The forName method in class Class.
The findSystemClass method in class ClassLoader.
The loadClass method in class ClassLoader.
but no definition for the class with the specified name could be found.
Usually, this happens when trying to open a connection manually in this form:
String jdbcDriver = "...'; //name of your driver
Class.forName(jdbcDriver);
Or when you refer to a class that belongs to an external library and strangely this class cannot be loaded when the application server tries to deploy the application.
Let's see the meaning of java.lang.NoClassDefFoundError (emphasis mine):
Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
The last part says it all: the class existed at compile time i.e. when I compiled the application through my IDE, but it is not available at runtime i.e. when the application is deployed.
how can I fix it?
In Java web applications, all third party libraries used by your application must go in WEB-INF/lib folder. Make sure that all the necessary libraries (jars) are placed there. You can check this easily:
- <webapp folder>
- WEB-INF
- lib
+ jar1
+ jar2
+ ...
- META-INF
- <rest of your folders>
This problem usually arises for JDBC connectivity jars (MySQL, Derby, MSSQL, Oracle, etc.) or web MVC frameworks libraries like JSF or Spring MVC.
Take into account that some third party libraries rely on other third party libraries, so you have to add all of them in WEB-INF/lib in order to make the application work. A good example of this is RichFaces 4 libraries, where you have to download and add the external libraries manually.
Note for Maven users: you should not experience these problems unless you have set the libraries as provided, test or system. If set to provided, you're responsible to add the libraries somewhere in the classpath. You can find more info about the dependency scopes here: Introduction to the Dependency Mechanism
In case the library must be shared among several applications that will be deployed on your application server e.g. MySQL connector for two applications, there's another alternative. Instead of deploying two war files each with their own MySQL connector library, place this library in the common library folder of the server application, this will enable the library to be in the classpath of all the deployed applications.
This folder vary from application server.
Tomcat 7/8: <tomcat_home>/lib
JBoss 7/Wildfly: <jboss_home>/standalone/lib
The class must exist under WEB-INF/classes or be inside a .jar file under WEB-INF/lib. Make sure it does.
Same problem happen with me.
Might be possible one of your libraries are using some classes internal which is not available
in your lib or maven dependency pom.xml.
Thats means you have analyze your error logs and identify these classes and then import all dependencies in maven or lib folder.
I have fixed this error by the same way.
because some of my libraries are using activation.jar and json.jar internally.
I developer a web application using Java. When I deploy it to my application server (Jetty, Tomcat, JBoss, GlassFish, etc.) throws an error. I can see this error message in the stacktrace:
java.lang.ClassNotFoundException
Or
java.lang.NoClassDefFoundError
What does this mean and how can I fix it?
What does this mean?
First, let's see the meaning of java.lang.ClassNotFoundException:
Thrown when an application tries to load in a class through its string name using:
The forName method in class Class.
The findSystemClass method in class ClassLoader.
The loadClass method in class ClassLoader.
but no definition for the class with the specified name could be found.
Usually, this happens when trying to open a connection manually in this form:
String jdbcDriver = "...'; //name of your driver
Class.forName(jdbcDriver);
Or when you refer to a class that belongs to an external library and strangely this class cannot be loaded when the application server tries to deploy the application.
Let's see the meaning of java.lang.NoClassDefFoundError (emphasis mine):
Thrown if the Java Virtual Machine or a ClassLoader instance tries to load in the definition of a class (as part of a normal method call or as part of creating a new instance using the new expression) and no definition of the class could be found.
The searched-for class definition existed when the currently executing class was compiled, but the definition can no longer be found.
The last part says it all: the class existed at compile time i.e. when I compiled the application through my IDE, but it is not available at runtime i.e. when the application is deployed.
how can I fix it?
In Java web applications, all third party libraries used by your application must go in WEB-INF/lib folder. Make sure that all the necessary libraries (jars) are placed there. You can check this easily:
- <webapp folder>
- WEB-INF
- lib
+ jar1
+ jar2
+ ...
- META-INF
- <rest of your folders>
This problem usually arises for JDBC connectivity jars (MySQL, Derby, MSSQL, Oracle, etc.) or web MVC frameworks libraries like JSF or Spring MVC.
Take into account that some third party libraries rely on other third party libraries, so you have to add all of them in WEB-INF/lib in order to make the application work. A good example of this is RichFaces 4 libraries, where you have to download and add the external libraries manually.
Note for Maven users: you should not experience these problems unless you have set the libraries as provided, test or system. If set to provided, you're responsible to add the libraries somewhere in the classpath. You can find more info about the dependency scopes here: Introduction to the Dependency Mechanism
In case the library must be shared among several applications that will be deployed on your application server e.g. MySQL connector for two applications, there's another alternative. Instead of deploying two war files each with their own MySQL connector library, place this library in the common library folder of the server application, this will enable the library to be in the classpath of all the deployed applications.
This folder vary from application server.
Tomcat 7/8: <tomcat_home>/lib
JBoss 7/Wildfly: <jboss_home>/standalone/lib
The class must exist under WEB-INF/classes or be inside a .jar file under WEB-INF/lib. Make sure it does.
Same problem happen with me.
Might be possible one of your libraries are using some classes internal which is not available
in your lib or maven dependency pom.xml.
Thats means you have analyze your error logs and identify these classes and then import all dependencies in maven or lib folder.
I have fixed this error by the same way.
because some of my libraries are using activation.jar and json.jar internally.
I am working on a portlet project and came across a problem with 2 classes with same name (including packages) in different .jar files. I have com.ibm.ws.webcontainer.jar as a default WebSphere library and jsf-impl.jar which is necessary for some JSF features.
The problem comes out when PortletFacesContextFactoryImpl class (another JSF class) tries to get access to com.sun.faces.util.Util.parameterNonNull(Object arg) method and I get NoSuchMethodError.
I tried setting classloader policy to PARENT_LAST, this doesn't help. I can't remove com.ibm.ws.webcontainer.jar from the server, but when I try to use Util class in my code, the only option is the class from it, not from jsf-impl.jar. jsf-impl.jar is included into Java Build Path.
How can this problem be solved since I cannot alter PortletFacesContextFactoryImpl source and move .jar with wrong class?
Parent Last should be your solution. WebSphere Portal deploys portlet application with Parent Last as default, but it does not hurt to double check it at the WebSphere Application Server Integrated Solutions Console (Admin Console) >
However, it also depends on your portlet application setup. I assume it is com.sun.faces.util.Util which is troubling you. On my system, this class is located in jsf-impl.jar and the Application Server Web Container. In order to get it to work, jsf-impl.jar needs to be placed in the WEB-INF/lib directory of your portlet application. To verify that, use the Class Loader View of WAS: Admin Console > Troubleshooting > Class loader viewer > WebSphere_Portal > Applications and then the your portlet application. It must start with PA. Switch to the table view and search for the class.
You also mentioned the Java Build Path. This is another topic and depends on your IDE - assumingly Eclipse. Check the Order and Export tab, jsf-impl.jar should be placed at the top, so that it overrules the server runtime classpath entries.
PARENT_LAST classpath setting will help you. However, for this setting to be done, your portlet muste be packaged as a EAR. If your portlet is packaged as a war and you configure the classpath settings manually, they get erased everytime you deploy the portlet.
I am deploying a WAR into a Tomcat 6 or Tomcat 7 server on a Windows 2003 Server box. The error looks something like
java.lang.Exception: Error initializing iSec web service proxy: Unable to create JAXBContext for generated packages: "com.integrity_apps" doesnt contain ObjectFactory.class or jaxb.index.
which I was getting previously when tools.jar was not in the classpath of my application. I was running the grails app from STS with the default web container, and I was able to fix this by re-installing JUST the JDK with tools.jar in the lib dir, and making sure JAVA_HOME was set correctly.
I have tried the same steps on the server - only installing the JDK, making sure JAVA_HOME is pointing to it, and dropping my WAR in the Tomcat container. I am still getting the error. Can anyone suggest why this may be happening?
As a further datapoint, I have noticed that if, on the server, I run the Tomcat7.exe from the command prompt directly (JAVA_HOME is set as a system variable), the error goes away. If I run it from the service manager, the error comes back.
Thanks
Looks like "com.integrity_apps" is your package containing your JAXB bean classes? I think it's missing ObjectFactory class within the package.
Check if there is a package called "com.integrity_apps" and if there is a class named ObjectFactory in that package. If not you may want to add it or use other ways to let JAXBContext know how to create your JAXB beans. This question on SO may be helpful:
Do you always need an ObjectFactory class when using JAXB?
In our application(applet) I want to enable export functionality if one of the required jars is found. I do not want to add this jar applet references to avoid download size.
I am using Class.forName with one of the classed to check whether particular is available. In local machine Class.forName call retruns an instance although the jar is not in any of the class paths.
Can anybody explain tomcat class discovery mechanism.
Applets run at the client side(inside the browser of the user) not on the Tomcat web server, so this is unrelated to Tomcat.
You'd want to investigate how Applet classloaders work.
Usually they will try to downloading the classes from the web server under the same Url as the applet was fetched from. So if the applet is at http://www.example.com/Hello/HelloApplet
and needs the class foo.bar.MyClass it will try to download http://www.example.com/Hello/foo/bar/MyClass.class if it isn't found locally.
Based on your description of having an Applet I don't see any option but to include the jar file in the applet tag as the applet runs on the client side.
You could set HTTP cache headers for the jar files to allow the client browser to cache them, therefore, you only pay the download cost only once.
For frequently changing jar files include the a version number in the jar file name to avoid client side caching issues with same named but contentually different jars.
Edit: Although the question is about the way tomcat discovers the jars I think the root cause of the problem is elsewhere.
In Tomcat 6 on the server side Tomcat searches the $TOMCAT_HOME/lib and WEB-INF/lib directories for your jar files. If you add or remove files there you usually need to restart the entire Tomcat instance.
Edit2:
Your experience about locating the jar file might be because you run the HTML page from the same directory where your webapp resides or you have the JAR file in a common place or common classpath location (for example in the JRE/lib/ext directory).
I am having a hard time following your question. Are you trying to download classes into an applet if a particular runtime condition is met? From 6u10 I believe you could dynamically download extensions with DownloadService. Going back to 1.2, you can use URLCLassLoader.newInstance, although that wont be so good on the cache side of things.
This question isn't very clear. Tomcat and Applets are completely different in terms of class loading. Applets have a security manager that prevents certain things, such as loading arbitrary classes. They have to download the classes from the web server. The web server doesn't have to be tomcat or even Java; the applet files are just files served over plain HTTP.
As for Tomcat, this article explains version 6's classloading. In particular, Tomcat uses a heirarchy of classloaders to find classes. There are several well-known locations where jars are automatically loaded, such as $CATALINA_HOME/lib or $CATALINA_HOME/shared/lib. It also loads the web-app's own jars and classes. The classloaders work as follows:
The bootstrap class loader looks in the core Java classes folders.
The system class loader looks in the $CATALINA_HOME/bin/bootstrap.jar and
$CATALINA_HOME/bin/tomcat-juli.jar
The WebAppX class loader looks in WEB-INF/classes and then WEB-INF/lib
The common class loader looks in $CATALINA_HOME/lib folder.
The shared class loader looks in $CATALINA_HOME/shared/classes and $CATALINA_HOME/shared/lib if the shared.loader property is set in conf/catalina.properties file.
Reason: One of the other libraries(jars) referenced earlier had the class I was looking for.