Skip to main content

ClassNotFoundException

Every programmer would have encountered a ClassNotfoundException somewhere in the development lifecycle. Many times we search for reasons why this is happening and i have seen many times people spending long hours to find why this is happening. This is particularly seen with web applications which are deployed in a webserver like tomcat or an app server like Weblogic or JBoss.In the case of a normal desktop java application, this can be fixed by adding the required class or the library that contains the class to the classpath. This way with Java 1.2, classpath classloader will load the class and the issue is fixed.

For a web application this may not be as staightforward. Some times i have seen people adding the class to the classpath of the webserver and still getting the error again.

Now to identify and fix these issues we need to understand that java supports many types of classloaders. The main one being bootstrap classloader responsible for loading Java API. The other one is the classpath classloader responsible for loading the classes refered in the classpath of the java. In the case of web application , the webserver uses it own user defined class loader to load the classes from the WAR file. Based on java security architecture a class loaded by a classloader can only see classes loaded by it. Then you would wonder how did a userdefined classloader access classes loaded by the bootstrap classloader if it can only see classes loaded by it. This is not true. The classloaders follows a parent child delegation model. If user defined class loader (in this cases , the classloader who loads classes from WAR) is required to load a class it asks the classloader's parent to load it and the parent will ask its parent this chain goes on and if none of the parent can load then it is upto the userdefined classloader to load it and if it cannot load , classnotfoundexception occurs.

I will try to explain this with an example.

Consider the case of a WAR file in which Class A is included in the WAR file. Class A references Class B. But Class B is not included in the WAR file. Infact someone has added it to the classpath of the webserver for some reason. Hence when the web classloader loads Class A, it finds the reference to Class B and it tries to load Class B when the method which uses Class B is invoked on Class A. For this it will ask its immediate parent and finally it will be loaded by the classpath classloader and returned. No issues here. No ClassNotFoundException.

Consider the case in which Class A is put in the webserver's class path and Class B is included in the WAR file. Here when web classloader (classloader responsible for loading classes from the WAR file. ) is required to load Class A, it asks its immediate parent and the chain continues and finally Class A is loaded by the classpath classloader and is returned. Now since Class B is not loaded by classpath classloader and Class A is loaded by classpath classloader when the method which uses Class B is invoked on Class A, a ClassNotFoundException would be thrown.

This is because classpath classloader can only ask its parent to load class and not its child classloader. This means classpath classloader doesn't know about Class B loaded by the Web Classloader. The reverse is true. Web Classloader will have access to classes loaded by its parent.
To solve the above ClassNotFoundException put both classes in the WAR file . Another option is to put Class A in WAR and Class B in classpath.

Pointer : Include all classes in the WAR file. Don't put any application specific classes in the webservers classpath. The above example was taken just to explain the classloader working.


Comments

These are some of the subtlities with Application servers. In more complex cases you will get ClassCastException when try to use a object instantiated by one classloader in another classloader.

Popular posts from this blog

Java - Too Many web frameworks

Hmm......... Java Web technology is exploding with many web frameworks promoted by the industry and many by opensource. Too many frameworks to choose from is a bad thing or good thing ?. Read on and judge yourselves. May be too much of anything is bad. Just look at the list below. JSF Spring MVC Tapestry Struts 2 ADF from Oracle Cocoon Maverick JBoss seam This is a never ending list. There are many more. Ofcourse not all are mainstream nowadays. Look at Microsoft stack , you mainly have ASP .NET and that's it. It has grown well.You need to learn only that and you focus all your skills in that web framework.It has accumulated many components and matured into a very robust RAD web application framework. The problem with the Java stream is you work on a particular web framework for sometime and all of a sudden you have to work in another web framework for another project.Hence the experiance one gains by working in a particular framework for long time, gets lost. This definitly lowers...

Using Database login Module in JBoss

This post is a detailed description on how to use the database login module in JBoss with a J2EE Application. Scenario There is a EJB and we want to restrict the access to this ejb's method to an authenticated user having a particular role. The EJB is accessed from a standalone Java Client using Remote Lookup. Implementation The EJB is HelloSSB and the roles allowed are admin and user. First step is to write the EJB The source code is given below. This is a stateless session bean. package com.prem.ejb; import javax.annotation.PreDestroy; import javax.annotation.Resource; import javax.annotation.security.RolesAllowed; import javax.ejb.SessionContext; import javax.ejb.Stateless; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import org.jboss.annotation.security.SecurityDomain; @Stateless @SecurityDomain ("helloworld") public class HelloSSB implements HellioIntf{ @PersistenceContext(unitName = "EntApp") EntityManager em; @Reso...