2 Replies Latest reply on Jun 21, 2006 10:36 PM by brian.stansberry

    Use of Region classloader outside of marshalling

    brian.stansberry

      The http session repl code currently has a direct reference to the JBoss Cache instance. It gets this by creating an MBean proxy to the cache and then calling the getInstance() method on the proxy.

      According to what I teach in the Advanced class, this is bad -- one service should not hold a reference to another, but rather should work through a proxy and the JXM bus. So, I tried to fix it by just working through the proxy.

      I found that this didn't work -- if I called getObject() through the JMX bus PojoCache would not be able to create instances of any of my webapp classes. Turns out that when you call through JMX, MBeanServerImpl sets the TCL to the target service's classloader before making the invocation. Since the cache's classloader can't see the webapp classes, the getObject() call fails.

      Wanted to get people's thoughts on 2 possible solutions:

      1) To hell with what we teach in Advanced -- continue invoking operations directly on the cache, not through the JMX bus. I believe with the MC services will have direct references to each other anyway.

      2) Modify PojoCache so it uses any registered classloader before attempting to instantiate objects:

      public Object _getObject(Fqn fqn) throws CacheException
       {
      
       ClassLoader prevCL = Thread.currentThread().getContextClassLoader();
       try
       {
       if (regionManager_ != null)
       {
       regionManager_.setUnmarshallingClassLoader(fqn);
       }
       return delegate_._getObject(fqn);
       }
       finally
       {
       Thread.currentThread().setContextClassLoader(prevCL);
       }
       }
      


      This latter approach worked fine. It seems valid too -- if the user registered a classloader for a region, having it be in effect before instantiating pojos in the region seems reasonable. But, I'm not sure if it has any side effects.

        • 1. Re: Use of Region classloader outside of marshalling

          Second approach sounds fine except then every PojoCache (and also TreeCache) calls from Tomcat will need to register with the marshalling classloader first? Well, PojoCache APIs are limited but not TreeCache though.

          Most of the time you won't need this since:

          1. You don't need to set the region marshaller
          2. Only replication layer needs to be aware of the region class loader.

          What we need is an AOP classloader advice that we can turn it on only when needed.

          • 2. Re: Use of Region classloader outside of marshalling
            brian.stansberry

            Any application that needs to replicate classes that aren't visible to the CL that loaded jboss-cache.jar will need to register a classloader anyway; otherwise replication won't work.

            I believe the only API where this is an issue is getObject() -- AFAIK that's the only one that creates new instances of user classes.