10 Replies Latest reply on Aug 8, 2008 5:13 AM by Scott Stark

    Remoting and remote classloading

    Ron Sigal Master

      In the course of working on JBREM-962 "Remote classloading does not work with Isolated EARs", I've realized that

      1) Remoting has its own remote classloading facility, and
      2) the Application Server runs an RMI classloader facility.

      In the "EJB/JBoss" forum thread "Serializable no remote classloading" (http://www.jboss.com/index.html?module=bb&op=viewtopic&t=126930&postdays=0&postorder=asc&start=0), Dimitris asked

      "dimitris@jboss.org" wrote:

      Ron, and yet another question is could this be made to work with the existing classloading service at port 8083?

      More so that fixes/features to the classloading service go into one place.


      I don't think we would want to trade in Remoting classloading, since Remoting should be able to run independently, but probably Remoting should be able to use the JBossAS classloading facility as well as its own.

      I haven't looked at the Remoting 3 code yet, so maybe this note is unnecessary. I'm just posting it so that I don't forget about the issue.

      -Ron

        • 1. Re: Remoting and remote classloading
          Trustin Lee Apprentice

          Good to know. Thanks for sharing the information!

          • 2. Re: Remoting and remote classloading
            Scott Stark Master

            I'm running into a similar issue where the remoting class loader (org.jboss.remoting.loading.RemotingClassLoader) logic to ask the parent class loader before the user class loader is reversing the class loading policy of the javaee app client container. This results in inconsistent classes as bean interfaces are being loaded twice.

            At a minimum, there needs to be a parent first flag that allows the user class loader to be tried first. The description of the fix for JBREM-962 I see is too specific to the jboss4x class loader architecture, so I'm going to create a new issue for 2.4.0.GA.

            • 4. Re: Remoting and remote classloading
              Ron Sigal Master

              On porting JBREM-962 "Remote classloading does not work with Isolated EARs" to JBossAS 5 and Remoting 2.4:

              "scott.stark@jboss.org" wrote:


              "ron.sigal@jboss.com" wrote:

              If RemotingClassLoader can't find a class locally, it will try to contact a Connector with a MarshallerLoaderHandler, which will send back a class if it can find it. For Remoting 2.2 and EAP 4.2/4.3, I made it possible to configure a Connector with the object names of a set of loader repositories (which come from jboss-app.xml files), so that MarshallerLoaderHandler can search for classes in scoped EARs. At first I thought you were saying that the TCL was a magic bullet I could use in place of external configuring, but I see that that's probably not the case. So I guess my question is: "Are there equivalent bean names, either for classloaders or repositories, that I can use in place of the JMX object names?".


              There are bean names, but the remoting layer should not end up trying to marshall things it does not know about and introduce a dependency on a server specific class loading implementation. The TCL is a magic bullet when the call has passed onto the handler. Outside of that, the remoting layer should not have to deal with class loading.


              Without access to classloaders other than its own, Remoting's remote classloading facility would be crippled, which was the genesis of JBREM-962. A user had EJB A and EJB B in two different scoped EARs, and he wanted EJB A to call a method on EJB B that returns an instance of a class that was unavailable to EJB A. With the fix from JBREM-962, the unmarshaller in EJB A can download the missing class by contacting Remoting's MarshallerLoaderHandler running in a Connector "affiliated" with the EJB3 Connector that serves EJB B. But that only works if the user configured the EJB3 Connector that serves EJB B with the name of the right classloader repository.

              I would argue that in this situation, Remoting's MarshallerLoaderHandler *is* the handler responsible for setting the TCL, though it's outside of the usual channels for mapping applications to classloaders.

              I guess the basic question is, do we want to continue to support Remoting's independent remote classloader facility? Or should Remoting just depend on the Application Server's RMI classloader facility?

              • 5. Re: Remoting and remote classloading
                Ron Sigal Master

                 

                "scott.stark@jboss.org" wrote:

                the remoting layer should not end up trying to marshall things it does not know about and introduce a dependency on a server specific class loading implementation.


                I guess injecting a list of classloaders would be pretty general.

                • 6. Re: Remoting and remote classloading
                  Scott Stark Master

                   

                  "ron.sigal@jboss.com" wrote:

                  Without access to classloaders other than its own, Remoting's remote classloading facility would be crippled, which was the genesis of JBREM-962. A user had EJB A and EJB B in two different scoped EARs, and he wanted EJB A to call a method on EJB B that returns an instance of a class that was unavailable to EJB A. With the fix from JBREM-962, the unmarshaller in EJB A can download the missing class by contacting Remoting's MarshallerLoaderHandler running in a Connector "affiliated" with the EJB3 Connector that serves EJB B. But that only works if the user configured the EJB3 Connector that serves EJB B with the name of the right classloader repository.

                  This is a form of rmi remote class loading, but that is simply a feature, not a crippling issue in my view. In general that usage is not possible because if the caller does have a class from ejb B that conflicts with it due to a local version difference, it has to be marshalled into the class loader space of ejb A.

                  "ron.sigal@jboss.com" wrote:

                  I would argue that in this situation, Remoting's MarshallerLoaderHandler *is* the handler responsible for setting the TCL, though it's outside of the usual channels for mapping applications to classloaders.

                  I guess the basic question is, do we want to continue to support Remoting's independent remote classloader facility? Or should Remoting just depend on the Application Server's RMI classloader facility?

                  I'm not saying we should not have a remote class loading feature to pull classes across the wire. I'm saying that its a pure delegation facility that requires the actual class loader to be provided to the remoting layer. A potential problem I see with the MarshallerLoaderHandler is that is calling the ServerInvoker for a class loader. A protocol specific handler is not going to know how to get class loaders for all of the invocation targets in use. Ejb3 is complete different from ejb2.

                  "ron.sigal@jboss.com" wrote:

                  I guess injecting a list of classloaders would be pretty general.

                  Yes, if we can have an application level bean register its class loader with the remoting layer to enable remote class loading, that is what we want. This would also allow the application layer to wrap its class loader in a filtered class loader with a policy that restricts what content can actually be remoted. Registering a class loader with remoting should be a priviledged operation with a security check to ensure only application framework code can perform the registration.


                  • 7. Re: Remoting and remote classloading
                    Ron Sigal Master

                     

                    "scott.stark@jboss.org" wrote:

                    A potential problem I see with the MarshallerLoaderHandler is that is calling the ServerInvoker for a class loader.


                    Right, pre-JBREM-962, that's all it did, which restricted the facility to Remoting's classloader. Now, if that doesn't work, it will try all the configured classloader repositories. E.g., if the Connector MBean is configured like

                     <mbean code="org.jboss.remoting.transport.Connector"
                     name="jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3">
                     <depends>jboss.aop:service=AspectDeployer</depends>
                     <attribute name="Configuration">
                     <config>
                     ...
                    
                     <repositories>
                     <repository>jboss.remoting:loader=titan1.ear</repository>
                     <repository>jboss.remoting:loader=titan2.ear</repository>
                     </repositories>
                    
                     ...
                     </config>
                     </attribute>
                     </mbean>
                    


                    where, for example, jboss.remoting:loader=titan1.ear comes from

                    <jboss-app>
                     <loader-repository>jboss.remoting:loader=titan1.ear</loader-repository>
                    </jboss-app>
                    


                    then MarshallerLoaderHandler will also try jboss.remoting:loader=titan1.ear and jboss.remoting:loader=titan2.ear.

                    What I'd like to do is replace the "repositories" element with a list of classloaders.

                    "scott.stark@jboss.org" wrote:

                    Yes, if we can have an application level bean register its class loader with the remoting layer to enable remote class loading, that is what we want.


                    I was thinking more in terms of declarative injection by way of *-beans.xml files. I'm not sure I see how an application level bean would get access to Remoting ... . Actually, that raises a question I've been meaning to figure out: What is the microcontainter/POJO analog to grabbing an MBeanServer and accessing an MBean by way of its object name?

                    "scott.stark@jboss.org" wrote:

                    if we can have an application level bean register its class loader ... Registering a class loader with remoting should be a priviledged operation with a security check to ensure only application framework code can perform the registration.


                    I'm missing something. If "application framework code" means the Application Server, then these statements sound contradictory ... . Also, is there a way for a Connector method to check that it's being called by JBoss code?

                    "scott.stark@jboss.org" wrote:

                    simply a feature, not a crippling issue in my view.


                    I won't let this hold up the 2.4.0.SP1 release unnecessarily.


                    • 8. Re: Remoting and remote classloading
                      Scott Stark Master

                       

                      "ron.sigal@jboss.com" wrote:

                      I was thinking more in terms of declarative injection by way of *-beans.xml files. I'm not sure I see how an application level bean would get access to Remoting ... . Actually, that raises a question I've been meaning to figure out: What is the microcontainter/POJO analog to grabbing an MBeanServer and accessing an MBean by way of its object name?

                      There is a KernelRegistryPlugin that allows for accessing info about a bean, but typically this is done by injection using the name.

                      "ron.sigal@jboss.com" wrote:

                      I'm missing something. If "application framework code" means the Application Server, then these statements sound contradictory ... . Also, is there a way for a Connector method to check that it's being called by JBoss code?

                      Yes, application framework code here are the server containers and application metadata. An application wanting remote class loading would include a -jboss-beans.xml that wires the deployment class loader to the remoting connector. There is also a jboss-classload*.xml that could be used to define the class loader bean name so its known. Maybe there is a pattern such that its not necessary to use jboss-classload*.xml for this.

                      The Connector would simply have a permission check. The permission would be mapped to jboss code by the permission CodeSource. Whoever sets up the security policy effectively defines jboss/server code from application code based on the permission urls.


                      • 9. Re: Remoting and remote classloading
                        Ron Sigal Master

                         

                        "scott.stark*jboss.org wrote:

                        The Connector would simply have a permission check. The permission would be mapped to jboss code by the permission CodeSource. Whoever sets up the security policy effectively defines jboss/server code from application code based on the permission urls.


                        Ah, so, just something like this:

                        public void setClassloaders(List classloaders)
                        {
                         SecurityManager sm = System.getSecurityManager();
                         if (sm != null)
                         {
                         sm.checkPermission(new RuntimePermission("setContextClassLoader"));
                         }
                        
                         this.classloaders = classloaders;
                        }