[Logo] Terracotta Discussion Forums (LEGACY READ-ONLY ARCHIVE)
  [Search] Search   [Recent Topics] Recent Topics   [Members]  Member Listing   [Groups] Back to home page 
[Register] Register / 
[Login] Login 
[Expert]
ClassCastException with EHCache  XML
Forum Index -> General
Author Message
danap

journeyman

Joined: 04/02/2008 08:15:50
Messages: 18
Location: Atlanta, GA
Offline

I have two web applications deployed into a Resin 3.1.6 container both of which are using an framework that we have developed. As such, they have pretty much the same structure from the service tier down. In this framework we define 4 hibernate session factories to access 4 different databases using EHCache as the second level cache provider. We also have another EHCache CacheManager defined for each that is used to cache objects constructed from results of calling a back-end EJB tier.

The first application starts fine and is functional but when I add the second application, I get ClassCastExceptions from the EHCache. See below.

I think what is happening here is that the first application starts and creates an instance of ALL_CACHE_MANAGERS with cache managers loaded using the first application's class loader. Then when the first CacheManager for the second application is loaded it attempts to iterate through this list, which gets faulted in from the tc server, and gets the ClassCastException because the CacheManagers in the list that was faulted in were loaded with the other webapp's class loader but the class that the reference is being converted to is loaded with the second web app's classloader.

Does that sound right?

If so, this means that the EHCache library needs to be loaded in a shared classloader. This makes my deployment more complicated and it is something I would like to avoid.

Code:
 [2008-08-12 21:41:46.505] Chained Exception Object: java.lang.ClassCastException
 [2008-08-12 21:41:46.505] 
 [2008-08-12 21:41:46.505] Description: net.sf.ehcache.CacheManager
 [2008-08-12 21:41:46.505] 
 [2008-08-12 21:41:46.505] Stack trace:
 [2008-08-12 21:41:46.505]       net.sf.ehcache.CacheManager.detectAndFixDiskStorePathConflict(CacheManager.java:299)
 [2008-08-12 21:41:46.505]       net.sf.ehcache.CacheManager.configure(CacheManager.java:275)
 [2008-08-12 21:41:46.505]       net.sf.ehcache.CacheManager.__tc_wrapped_init(CacheManager.java:218)
 [2008-08-12 21:41:46.505]       net.sf.ehcache.CacheManager.init(CacheManager.java)
 [2008-08-12 21:41:46.505]       net.sf.ehcache.CacheManager.<init>(CacheManager.java:205)
 [2008-08-12 21:41:46.505]       sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
 [2008-08-12 21:41:46.505]       sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
 [2008-08-12 21:41:46.505]       sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
 [2008-08-12 21:41:46.505]       java.lang.reflect.Constructor.newInstance(Constructor.java:494)
 [2008-08-12 21:41:46.505]       org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:96)
 
[WWW] [Yahoo!] aim icon [MSN]
danap

journeyman

Joined: 04/02/2008 08:15:50
Messages: 18
Location: Atlanta, GA
Offline

OK, I have made some progress.

I have moved the jars needed by EHCache into a directory outside of my web applications and put that directory in a -Djava.ext.dirs=... parameter to the JVM running the container.

This has corrected the problem with EHCache but when I attempt to use the application, I get exceptions from Hibernate where hibernate objects are getting ClassCastExceptions when getting data out of the cache.

I am confused how ClassLoaders and classes work together in terracotta.

In Java, classes are the same IF they have the same name AND the same class loader. So Webapp A and Webapp B can both have the Foo class but instances of Foo, one from A and one from B, would not be considered to be the same class. As such, any static variables created by Foo would have separate instances between Webapp A and Webapp B.

Say:
Code:
 import java.util.Map;
 import java.util.HashMap;
 public class Foo {
   public static Map bar = new HashMap();
 
   ...
 }
 


In terracotta the backend distinguishes classes by ClassLoader Name and Class Name. Therefore, Foo.bar in ClassLoader named RESIN_WEBAPP::/A would be different from Foo.bar in ClassLoader named RESIN_WEBAPP::/B. Right?

If so, then if I declare Foo.bar as a root there should be a separate root for each ClassLoader that loads the Foo class.

But this is not the behavior I am seeing. It appears as though, at least for static roots, there is only one cluster wide instance. For exaxmple, net.sf.ehcache.CacheManager.ALL_CACHE_MANAGERS is behaving as though there are is only one.
[WWW] [Yahoo!] aim icon [MSN]
teck

seraphim
[Avatar]
Joined: 05/24/2006 15:03:25
Messages: 1128
Offline

Your analysis is correct. Terracotta roots are not afforded any scope/isolation by the fact the root field is declared into classes from different classloaders. A root field is bound to a root name in terracotta and there is only a single global namespace.

It sounds like you're accessing objects between webapps due to the fact that the ehcaches are globally visible when clustered. Perhaps your cache names should be isolated per webapp?

Any reason why you didn't use regular system CLASSPATH instead of the extensions dir (or perhaps another loader comoon to both web apps)?


Tim Eck (terracotta engineer)
danap

journeyman

Joined: 04/02/2008 08:15:50
Messages: 18
Location: Atlanta, GA
Offline

Thanks Tim.

I used the java.ext.dirs because it was a quick way to move the classes up. The problem is that Resin does not give us easy access to the -classpath for the actual resin server JVM since that JVM is started by a watchdog application. I have done some more work on the Resin TIM to name the root and server class loaders. I am attempting to test this now. If that works I can move the jars into the server ClassLoader. I spoke with Santi and he indicated that it should work better since the classes in the ext dirs do not have access to the classes in the webapp.

As for isolating the web application's caches by cache name, this might be problematic. We use the ehcache.xml to define parameters for our cache's behaviors ( max items, max idle time, etc. ). I could use a different configuration mechanism that would take this into account but that is extra work.

Thanks
[WWW] [Yahoo!] aim icon [MSN]
 
Forum Index -> General
Go to:   
Powered by JForum 2.1.7 © JForum Team