ClassLoader issues with ClassCastExceptions and NoClassDefFoundError
Jan 18, 2006 6:19 AM
First off, I realize the topic of Resource Adapter ClassLoader problems has been posted and replied to dozens of time. The problem is most topics simply end with "just put the shared classes in the application server's classpath." Unfortunately, if this approach is taken, the application server must be shutdown and restarted in order to make any updates to the resource adapter. Simply put, this isn't a very good solution.
With this release of WebLogic Server, each resource adapter now uses its own classloader to load classes (similar to Web applications). As a result, modules like Web applications and EJBs that are packaged along with a resource adapter in an application archive (EAR file) do not have visibility into the resource adapter's classes. If such visibility is required, you must place the resource adapter classes in APP-INF/classes. You can also archive these classes (using the JAR utility) and place them in the APP-INF/lib of the application archive.
Make sure that no resource-adapter specific classes exist in your WebLogic Server system classpath. If you need to use resource adapter-specific classes with Web modules (for example, an EJB or Web application), you must bundle these classes in the corresponding module's archive file (for example, the JAR file for EJBs or the WAR file for Web applications).
This may work if multiple EJBs and the RAR are bundled and deployed as a single EAR with a shared APP-INF/lib directory, but what if the RAR is deployed seperately?
From my experience, if the EAR and the RAR are deployed seperately and an EJB in the EAR performs a JNDI lookup on the RA's ConnectionFactory this results in a NoClassDefFoundError. It makes sense since the EAR and RAR have difference ClassLoaders that by design do not have visibility into each other's classes.
To avoid the NoClassDefFoundError, I created a "rar-api.jar" that included only the Connection and ConnectionFactory interfaces for my RA and included only these interface classes in the APP-INF/lib directory of the EAR. Now, when an EJB performs a JNDI lookup it results in a ClassCastException. This also makes sense because even though they are the same classes they come from difference ClassLoaders and this also by design is supposed to result in a ClassCastException.
Going back to the suggestion made in other topics, I placed the "rar-api.jar" in the application server's classpath and now everything works. However, as stated before, this is not an acceptable solution.
How is anyone supposed to get a Resource Adapter to work in a realistic production environment where the application server cannot be restarted but a Resource Adapter must be redeployed from time to time?
Re: ClassLoader issues with ClassCastExceptions and NoClassDefFoundError
Mar 24, 2006 11:06 AM
I have myself been through this entire stack of problems, from ClassCastException to NoClassDefFoundError.
I think BEA should adopt a more friendly Class loading scheme (like some other app servers I wont mention) where the JCA classloader is the parent of all other application classloaders (EJBs, WebApps, EARs...). This allows any and all applications/modules to easily interact with the JCA adapter without having to bundle any JCA adapter specific classes and without having to tinker with the server's classpath.
At weblogic 9 we have the option of putting JCA specific classes in the <domain>/<server>/lib folder. This is definitely an improvement from 8.1, but still does not allow hot updates to these libraries.
I regularly deploy EJSs and WebApps as stand alone modules, and am thus forced to place JCA classes in the server's classspath.
Whenever I deploye EARs I avoid using the APP-INF folders because they are not a "standard" J2EE practice.
I wish all J2EE vendors would just come together and agree on one classloading scheme.