Sunday, January 17, 2010

Understanding Weblogic class loading



Yes! You need to understand class loading. I was also of the view that why do I need to go into the details of weblogic class loading, can’t I just develop and deploy j2ee applications on weblogic. And then you encounter following kind of problems
1-      Log4j is not working as expected, although you have configured it correctly.
2-      You get ClassCastException although you have included the library in your application.

I will explain the problems and solutions later, first class loading.

Class loading is a task of loading java classes and is performed by class loaders.  Class loaders are arranged in inheritance hierarchy this is called Delegation. Each class loader first requests super class loader to load requested class and if super fails it tries to load itself. In this way class loaders do not load classes already loaded by parent class loaders.

J2SE defines following levels of class loaders.  Please refer to figure 1.

1- 1-      Bootstrap class loader: is native code and its responsibility is to load JAVA_HOME/lib and JAVA_HOME/lib/ext.
2-  2-     System class loader: loads classes in CLASSPATH.

Weblogic replaces system class loader with its own version.
1-      Weblogic system class loader, loads weblogic classes.
2-      For each enterprise application (EAR) deployed on weblogic there are two instances of class loaders one for EJB and other for Web app as its child. For an EJB application only EJB Class loader is used and similarly for Web app. EJB Class loader is parent of Web class loader as typically web classes use EJBs. Note that there are separate instances of these class loaders for each deployed weblogic application, referred in docs as sibling class loaders. So, that classes loaded by one weblogic application are not visible to others. This enables weblogic applications to use different versions of single class / library.

If you create an enterprise application project, EJB Class loader loads classes/libraries of both EJB project and EAR project. Whereas Web class loader loads classes/libraries of web project only.  Suppose you have an enterprise project with following structure.

Enterprise Project
                Ear-Content
APP-INF
lib
ep_x1.jar
ep_x2.jar
Web Project
                Web-Content
Web-INF
lib
wp_x1.jar
ep_x1.jar
ej_x1.jar
ejbModule

Considering jars only, EJB Class loader will load ep_x1.jar, ep_x2.jar and ej_x1.jar. Web class loader will only load wp_x1.jar. And when it tries to load ep_x1.jar it will find out that its classes are already loaded by its parent class loader so it reuses.

Now let us add log4j support in your project. In order to avoid repetition you should add log4j.jar in Enterprise project’s APP-INF/lib folder and reference it from both Web and EJB projects. Do the same for all of your common libraries. What about log4j.properties? Where should we place the file? As you may know log4j automatically loads log4j.properties from CLASSPATH on startup (static loading). And in our current configuration log4j is loaded by EJB Class loader so we should place single properties file in EJB project.

EJB Project
log4j.properties
ejbModule


What if log4j is being used in weblogic e.g. someone placed it in {$DOMAIN_HOME}/lib folder? Since log4j is already loaded by weblogic system class loader, your project’s log4j.properties will not be statically loaded. Solution is to reload log4.jar but how? Here comes weblogic Filter class loader. In your enterprise project’s weblogic-application.xml add below lines

<wls:prefer-application-packages>
    <wls:package-name>org.apache.log4j.*</wls:package-name> 
</wls:prefer-application-packages>

Filter Class loader throws ClassNotFound exception on each of the classes configured as above, thus allowing child class loaders to themselves load classes. And this will solve our problem as EJB Class loader will load log4j.jar irrelevant of whether it is already loaded by parent class loaders and therefore allowing log4j to read our supplied log4j.properties.









No comments: