<?xml version="1.0"?>
<document>
  <properties>
    <title>Webapp libraries and EJB libraries</title>
  </properties>
  <body>

<section title="The Rule">
<p>
Never ever put your EJBs in your WEB-INF directories.  The same rule applies 
to any libraries needed by your EJBs.
</p>
</section>

<section title="The Consequences">
<p>
If you break the rule, you will be riddled with ClassCastExceptions like the following:
</p>
<PRE>
java.lang.ClassCastException
    at org.apache.jsp.test$jsp._jspService(test$jsp.java:102)
    at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:107)
    ...
</PRE>
<PRE>
java.lang.ClassCastException
    at com.sun.corba.se.internal.javax.rmi.PortableRemoteObject.narrow(PortableRemoteObject.java:293)
    ...
</PRE>
</section>

<section title="Java Classloading Rules">
<p>
By rule of the Java Language, two classes are only the same if they have the same type <B>AND</B> they were loaded by the same classloader!
</p>
</section>
<section title="Webapp Classloader vs. Common Classloader">
<p>
In Tomcat, each webapp has it's very own classloader, called it's <A HREF="http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html#Class%20Loader%20Definitions">Webapp Classloader</A>.
</p>
<p>
When OpenEJB is loaded into Tomcat, it is loaded into Tomcat's <A HREF="http://jakarta.apache.org/tomcat/tomcat-4.1-doc/class-loader-howto.html#Class%20Loader%20Definitions">Common Classloader</A>.
Classes in the Common Classloader are automatically available to all the Webapp classloaders.
Having OpenEJB in the Common Classloader makes OpenEJB and your EJBs available to all webapps.
</p>
<p>
There is an important thing to know about the Webapp Classloader; it will always load classes from the WEB-INF/classes or WEB-INF/lib directories even if the same class is available in the Common Classloader.
</p>
<p>
Remember the Java classloading rules?  If your webapp loads a class file from the Webapp Classloader and OpenEJB loads the same class file from the Common Classloader, are they the same class? NO, definitly not!
</p>
</section>

<section title="The Rule Revisited">
<p>
This brings us back to our rule: never ever put your EJBs in your WEB-INF directories.  The same rule applies 
to any libraries needed by your EJBs.
</p>
<p>
OpenEJB creates instances and implementations of the EJBHome and EJBObject using classes it finds in
it's classloader (the Common Classloader).  When your Servlet or JSP looks up an EJB, OpenEJB will 
generate an implementation of that bean's EJBHome interface and send it to the servlet.
</p>
<p>
If your servlet's classloader (the Webapp Classloader) already loaded the class into
it's classloader, you have a situation where the exact same class
exists in two different classloaders.  When
you try to cast one classloader's version to another classloader's
version, everything blows up.
</p>
</section>
  </body>
</document>
