Millies, Sebastian wrote:
-----Original Message-----
From: Simon Nash [mailto:[email protected]]
Sent: Wednesday, January 11, 2012 9:47 AM
To: [email protected]
Subject: Re: RMIBinding does not work with ContributionClassLoader
[snip]
So far so good – I now have a remote proxy. However, the attempt does
not quite work, because methods that have
parameter types which are not on the application classpath cannot be
invoked on that proxy:
When Tuscany instantiates the stub from the RMI registry it reloads
the method parameter types NOT using the
ContributionClassLoader for the contribution that contains the remote
service. So they do not match the parameter types
that are stored in the RMIReferenceInvoker (in the member variable
“remoteMethod”).
Thus, RMIReferenceInvoker# invokeTarget() will throw a
NoSuchMethodException!
[snip]
I suspect that RMI is searching the thread context class loader (TCCL)
when looking for the parameter types. The Java launcher gives TCCL an
initial value of the application classloader.
There's an API in the Thread class to change TCCL, but doing this is
an evil hack and I'd be hesitant to recommend it.
As an experiment, you could try setting TCCL to the contribution
classloader before making the RMI invocation and resetting it to its
previous value when the invocation returns. It would be interesting
to know whether that resolves the problem.
Simon
Thanks for the idea. It does not solve the problem, there is something
happening which I do not understand at all.
I can now successfully retrieve the remote method in the RMIReferenceInvoker
(which to me would indicate correct parameter types). But then I get an
IllegalArgumentException when actually invoking the method - as if the types
of the actual payload were different from the parameter types that had been
used for looking up the method (i.e. loaded by different classloader).
This new exception happens much deeper in the stack, so some strange things
may intervene. I attach the complete stack trace.
Here's my code around the remote call to switch the TCCL in my service
implementation class:
ClassLoader tccl = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader( getClass().getClassLoader() );
DataObject search = search( ctx, query ); // <-- remote call
Thread.currentThread().setContextClassLoader( tccl );
Yes, that's the code I was suggesting.
The stack trace tells me that the stub invocation on the reference side
succeeded (with correct/matching argument types) but the Tuscany RMI service
binding provider wasn't able to invoke the service method because of an
argument type mismatch on the service side. Does this provide any clues?
I also noticed the presence of PassByValueInterceptor in the stack trace
on both the reference and service sides. If this is copying argument
objects, there's a possibility that it's not using the correct/matching
classloader to create the copy.
Simon
-- Sebastian
IDS Scheer Consulting GmbH
Geschäftsführer/Managing Directors: Kamyar Niroumand, Ivo Totev
Sitz/Registered office: Altenkesseler Straße 17, 66115 Saarbrücken, Germany -
Registergericht/Commercial register: Saarbrücken HRB 19681
http://www.softwareag.com