2 Replies Latest reply on Feb 2, 2009 12:11 PM by fabratu

    RMI Dynamic Classloading

    dubacher

      Hi there.

      I have a problem when using the dynamic classloading feature of RMI for a non RMI-Class.

      Note:
      - The "WebService" which provides the class is up and running on the port 8083.
      - I use jboss-4.2.2

      The first problem:
      When the class X to be loaded dynamically is sent as instance to the client, the codebase is not set correctly to the WebServer running on port 8083. Instead the codebase comprises loads of "file:/...."-URLs. Therefore when the class X has to be loaded the client does not try to dynamically load the class from the server running on port 8083.
      I patched the class MarshalInputStream so that the codebase is set correctly on the client side. After having applied the patch the client now tries to load the class from the server...

      now the second problem:

      I sniffed the port 8083. The following HTTP get call is performed:

      GET /org/foo/bar/X.class HTTP/1.1
      User-Agent: Java/1.6.0_05
      Host: delgado:8083
      Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
      Connection: keep-alive

      Which is answered by the server with:

      HTTP/1.0 404 Not Found
      Content-Type: text/html


      I debugged the WebServer code and found out that classloader returned by the call "Thread.currentThread().getContextClassLoader();" is not able to load my class X.


      Any hints to my problem are appreciated.

      cheers,
      marco

        • 1. Re: RMI Dynamic Classloading
          dubacher

          Hi there.

          Unfortunately nobody replied to my initial post. With this post I would like to precise my initial post, hoping that somebody can help me:

          My setup:
          I have a JBoss (version 4.2.2) to which a war-file is deployed. The war-file contains a ServletContextListener which registers a ServerAccessService class in JNDI on startup. The ServerAccessService class extends from UnicastRemoteObject. So methods defined on ServerAccessService are accessible via RMI from remote clients. So far so good...

          What do I want to do?
          Let's assume ServerAccessService provides a method "public Foo getFoo (int id)". This method will return an instance of FooImpl which implements Foo. On the remote client I would like to deploy the Foo interface only (and not the class FooImpl). As RMI provides the feature of dynamic class loading it should be possible that FooImpl is loaded from the server as soon as an instance of FooImpl is transmitted to the client. So to wrap it up: When the remote client calls "getFoo(..)" it will get an instance of "FooImpl" which class should be dynamically loaded from the server.

          The problem:
          It doesn't work out!!! The configuration of the WebService in JBoss is as far as I know correct. WebService is running on port 8083; I also tried to load the class with the tomcat server running on 8080; the system property java.rmi.server.codebase is set etc.

          So now to my investigations:
          When the FooImpl class is transmitted to the client, a codebase property is sent along with the instance (The codebase is finally used on the client as a hint where to load the class from). But different from the classes like ArrayList etc. the codebase of FooImpl is not something like "http://myserver:8083" or "http://myserver:8080" but something like "file:/..............". So why that? The reason are ClassLoaders... obviously. When annotating the instances transmitted back to the client with the codebase, something like the following stack trace shows is executed:

          Daemon System Thread [RMI TCP Connection(6)-10.130.202.179] (Suspended) LoaderHandler.getClassAnnotation(Class)
          line: 174 RMIClassLoader$2.getClassAnnotation(Class<?>)
          line: 639 JBossRMIClassLoader.getClassAnnotation(Class) line: 112 RMIClassLoader.getClassAnnotation(Class<?>)
          line: 364 ConnectionOutputStream(MarshalOutputStream).annotateClass(Class<?>)
          line: 75 ConnectionOutputStream(ObjectOutputStream).writeNonProxyDesc(ObjectStreamClass, boolean)
          line: 1250 ConnectionOutputStream(ObjectOutputStream).writeClassDesc(ObjectStreamClass, boolean)
          line: 1203 ConnectionOutputStream(ObjectOutputStream).writeOrdinaryObject(Object, ObjectStreamClass, boolean)
          line: 1387 ConnectionOutputStream(ObjectOutputStream).writeObject0(Object, boolean)
          line: 1150 ConnectionOutputStream(ObjectOutputStream).writeObject(Object)
          line: 326 UnicastRef.marshalValue(Class<?>, Object, ObjectOutput) line: 274 UnicastServerRef.dispatch(Remote, RemoteCall)
          line: 315 ........


          Ok. So far so "good". Classes like ArrayList are loaded initially loaded by "SystemClassLoaders" but the class FooImpl is loaded by theWebAppClassLoader (yes you are the author of this class :-)). In the class LoaderHandler the "SystemClassLoader" are registered to return the defined codebase (i.e. the one defined with java.rmi.server.codebase) when the method getClassAnnotation is called. The WebAppClassLoader however doesn't belong to this list. That's why the LoaderHandler will return as codebase the URLs returned by the method WebAppClassLoader(URLClassLoader).getURLs. This is obviously something like "file:/...".

          So the client gets a instance of FooImpl and its classes codebase is something like "file:/....". Obviously it cannot find the class FooImpl on the local file system as it has not been deployed > ClassNotFoundException is final result.


          The question now: How do I solve this problem?
          - Do I need to configure my app differently so that the LoaderHandler will return the codebase defined by java.rmi.server.codebase for the WebAppClassLoader as well?
          - Is dynamic class loading not intended to be used with applications deployed as war?
          - ...?

          • 2. Re: RMI Dynamic Classloading
            fabratu

            dubacher, have you found a solution to this problem? If so, can you share it with us?

            If not, a somehow related issue is http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4179293#4179293

            I would *really* like to know the answers to the questions you posted here... eventually, an "official" opinion will be welcome...