-
1. Re: Setting the thread context class loader on mbean op disp
adrian.brock May 2, 2005 12:22 PM (in response to starksm64)I think chaining is likely to lead all sorts of linkage errors or Class Casts.
If you don't want an MBean to run under its own classloader you can do
this, e.g. just doing a plain registerMBean without specifying a classloader
will do this. Or could not use a JMX invocation and allow a getInstance()
method to bypass the JMX Bus.
A more general solution would be to add metadata on which operations
should be run in the caller classloader versus the deployment classloader
like lifecycle operations. -
2. Re: Setting the thread context class loader on mbean op disp
starksm64 May 2, 2005 2:31 PM (in response to starksm64)Yes, there is a red flag issue once you have a service trying to interact with multiple class loaders, but it should be possible if designed for this. The only classes that are subject to linkage errors and class cast expections are those that show up in the service's interface (ignoring any bugs due to caching of types by the class loader or other layers). This of course means a detyped interface in general. An interesting question is, if such an interface was modifed to use generics, is there any type leakage. As far as I understand the generics type nullifcation mechanism, the type binding would be in the client usage context and therefore its class loader context, but this is something I would like to verify, and verify that it works with type reloading in the client class loader.
-
3. Re: Setting the thread context class loader on mbean op disp
ben.wang May 10, 2005 6:55 PM (in response to starksm64)I have created a Jira for future reference:
http://jira.jboss.com/jira/browse/JBAS-1803
Meanwhile, I will try to get around that problem by using a MarshalledValue wrapper. It will have performance impact but it should work for now. -
4. Re: Setting the thread context class loader on mbean op disp
adrian.brock May 10, 2005 7:28 PM (in response to starksm64)I'm obviously looking at the wrong code since it is already setting
the correct TCL:
JBossCacheServiceprivate Object getUnMarshalledValue(Object mv) { if (mv == null) return null; // Swap in/out the tcl for this web app. Needed only for un marshalling. ClassLoader prevTCL = Thread.currentThread().getContextClassLoader(); Thread.currentThread().setContextClassLoader(tcl_); try { return ((MarshalledValue) mv).get(); } catch (IOException e) { e.printStackTrace(); return null; } catch (ClassNotFoundException e) { e.printStackTrace(); return null; } finally { Thread.currentThread().setContextClassLoader(prevTCL); } }
where tcl_ is coming from the Tomcat config. -
5. Re: Setting the thread context class loader on mbean op disp
adrian.brock May 10, 2005 7:31 PM (in response to starksm64)Please fix the e.printStackTrace()
while you are in this code.
And the double logging abomination.String str = cacheServiceName_ + " service to Tomcat clustering not found"; log_.error(str); throw new ClusteringNotSupportedException(str);
trace and throw - yes
error and throw just makes your eyes bleed as the console flashes past
with the all the duplicate logging. :-) -
6. Re: Setting the thread context class loader on mbean op disp
ben.wang May 10, 2005 8:00 PM (in response to starksm64)Yeah, you were looking at the wrong code. That marshalling/unmarshalling code works.
This is the code that failed:public Object getPojo(String sessionId, String key) { String realId = stripJvmRoute(sessionId); if(log_.isDebugEnabled()) { log_.debug("getPojo(): session id: " +sessionId + " key: " +key); } // Construct the fqn. Fqn fqn = getFieldFqn(realId, key); try { return proxy_.getObject(fqn); } catch (CacheException e) { e.printStackTrace(); throw new RuntimeException("JBossCacheService: exception occurred in cache getPojo ... ", e); } }
And this code will call JBossCacheAop (you will have to check out JBossCache module though. :-)
But you maybe right. Solution is then I will need to set tcl before calling getPojo regardless what.
Let me try. -
7. Re: Setting the thread context class loader on mbean op disp
adrian.brock May 10, 2005 8:22 PM (in response to starksm64)"ben.wang@jboss.com" wrote:
But you maybe right. Solution is then I will need to set tcl before calling getPojo regardless what.
Let me try.
No, because invoking the proxy will change the classloader.
Your fundamental problem (as I understand your description in JBCACHE-151)
is that the code that does the serialization/deserialization
doesn't understand classloader context. That is why you need the MarshalledValue.
Class.forName(String) is going to use the classloader that loads your jboss cache class
regardless of what JMX does.