| <?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> |