Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [riena-dev] Interface not visible from class loader!

Hi Olaf, Scott,

@Olaf,

I think your solution will work, but I am not a big fan of looking at the call stack. Also your solution confuses me because some variables like CLASSCONTEXT are static. Are you sure that this solution works even if multiple threads try to create a proxy at the same time with different bundles trying to do that ?

Not sure why that is any better than the buddy policy. Also the buddy policy thing not only deals with the interface itself but also with all return values or paramters. If they are not in the same package as the interface they need to be buddy to. Your solution would not help anymore.

@Scott: While that solution should work I guess, I am afraid that it makes the system way slower. I have already read somewhere in the internet that buddy policies are a timing problem. Because they mean that for every class the classloaded search a large list of bundles. If it would search all bundles, I believe the result could be even worse. Since they are not only consulted for the interfaces but possibly also for return values and parameters, I am not sure that way is a good idea.

but thanks for the input. I know BuddyPolicies are not ideal but they are currently the best way to handle this problem I know.

christian
Am 30.03.2009 um 09:40 schrieb Scott Lewis:

Hi Olaf and Rieners,

Also, you should see the OSGi manifest entry:

Dynamic-ImportPackage: *

What this does is tell the classloader for the bundle that contains this markup (e.g. the Riena Hessian bundle I expect) that it should look for
a class in every exported package within the current runtime.  As long
as the proxy interface class is exported, the hessian proxy factory code
would then find it.  You can scope it by package if you wish.

Scott


Olaf Fricke wrote:
Hi Yau, hi Christian,

I found another solution for the classloading issue, the does neither
need the buddy definition nor the dependency  to
org.eclipse.riena.communication.core.

To find such a solution, I had to dig into the code that throws the
java.lang.IllegalArgumentException. The reason for that exception is
that the HessianProxyFactory tries to construct a new
java.lang.reflect.Proxy instance. Because Hessian does not know
better, it gives the current context classloader to to javas
reflection classes. That classloader is the ContextFinder of Equinox.
When loading classes, the ContextFinder searches for the first class
of an non-internal bundle on the callstack and delegates the
classloading to that bundle. This bundle is the com.caucho.hessian
bundle and that bundle does indeed know nothing about any concrete
service interfaces.

My first try for a solution was to give the classloader of the
interface class to the rienaHessianProxyFactory (by calling
endpoint.getServiceInterfaceClass().getClassLoader(). This appoach
failed too, because Hessian tries to bind the Proxy instance to
another interface, too (com.caucho.hessian.io.HessianRemoteObject).
Too make this interface visible to the bundle that contains the
service interface, you can add a dependency to com.cauche.hessian. I
tried this and it worked. But that appoach would require that each api
bundle is dependend of hessian, which is no good idea.

Instead, I looked for another solution and detected that the bundle
that creates the service proxy (for example
org.eclipse.riena.communication.sample.pingpong.client.config) knows
both interfaces, because is has indeed dependencies to
com.cauche.hessian and to the service interface. The remaining task
was to find a way to give the classloader of that bundle to the
rienaHessianProxyFactory.

Therefore I added the following code to the class
org .eclipse .riena .internal.communication.factory.hessian.RemoteServiceFactoryHessian,
to be able to get the current execution stack:

   // copied from org.eclipse.osgi.internal.loader.BundleLoader
   static final class ClassContext extends SecurityManager {
       // need to make this method public
       public Class<?>[] getClassContext() {
           return super.getClassContext();
       }
   }

   @SuppressWarnings("unchecked")
   public final static ClassContext CLASS_CONTEXT = (ClassContext)
AccessController.doPrivileged(new PrivilegedAction() {
       public Object run() {
           return new ClassContext();
       }
   });

In the method
RemoteServiceFactoryHessian.createProxy(RemoteServiceDescription
endpoint) I replaced the line
           Object proxy =
rienaHessianProxyFactory.create(endpoint.getServiceInterfaceClass(),
uri, classLoader);
with the following code:
// determine the classloader for the class that called the factory
     Class<?>[] classContext = CLASS_CONTEXT.getClassContext();
     ClassLoader classLoader =
Thread.currentThread().getContextClassLoader();
     for (int i = 1; i < classContext.length; i++) { // starting at 1
is required due to the inner class
         Class<?> clazz = classContext[i];
         if (clazz != null && clazz != this.getClass() && clazz !=
RemoteServiceFactory.class && clazz != ProxyFactory.class) {
                   classLoader = clazz.getClassLoader();
             break;
         }
     }

           Object proxy =
rienaHessianProxyFactory.create(endpoint.getServiceInterfaceClass(),
uri, classLoader);
The main idea is to lookup the first class from the callstack that
does not belong to the proxy creation and give the classlaoder of that
class to Hessian.

I tried my solution on the PingPong sample and it worked without the
buddy definition and without a dependency from the pingpong.common
bundle to the org.eclipse.riena.communication.core bundle.

Best regards,
Olaf


------------------------------------------------------------------------

_______________________________________________
riena-dev mailing list
riena-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/riena-dev


_______________________________________________
riena-dev mailing list
riena-dev@xxxxxxxxxxx
https://dev.eclipse.org/mailman/listinfo/riena-dev



Back to the top