6 Replies Latest reply on Jan 5, 2011 9:13 AM by alesj

    EJB's and classloading

    mbalazs

      Hello!

       

      Sorry for double posting it, I posted this question to the JBoss AS deployment forum yesterday, but I just found this forum and I think that more people read it here who may be able to help me with this.

       

      I have successfully managed to get myself in classloading hell. And I would be glad if someone could help me out with this because I couldn't find enough information to resolve this problem. I am using JBoss AS 5.1.

       

      Here is my scenario:

       

      I have two top level EAR's: Service.ear and Application.ear

       

      Service.ear contains an MBean and a WAR, and has no classloader isolation defined or any other classloader settings modified.

      Application.ear has an EJB module and a WAR, and has an isolated classloader repository defined in the ear's jboss-app.xml, with java2ParentDelegation enabled.

       

      The problem is the following:

      The MBean in Service.ear is an event dispatcher, and the Application.ear's WAR registers an event listener object in the MBean during servlet context initialization. When the MBean dispatches the event, it can call the event listener registered by the application without problems, however, the event listener needs to use an SFSB, and at that point it fails because it can't access the EJB's remote interface:

       

      2011-01-03 16:30:41,856 ERROR [...] (http-droolsdemo-portal%2F172.16.3.28-8080-1) Could not lookup GwtConsoleClient session bean: javax.naming.NamingException: Could not dereference object [Root exception is java.lang.RuntimeException: Can not find interface declared by Proxy in our CL + BaseClassLoader@2296c1d{vfszip:/opt/jboss-epp-5.0/jboss-as/server/default/deploy/Service.ear/}]

       

      (GwtConsoleClient's classes are in the EJB module of Application.ear)

       

      I can see that the problem is that the whole call chain was started from within the Service.ear's context, thus it uses its class loader domain. It is unclear to me that what exactly  "BaseClassLoader@2296c1d{vfszip:/opt/jboss-epp-5.0/jboss-as/server/default/deploy/Service.ear/}" means.

       

      Does it refer to a classloader repository?

      If this is specific to the new classloading model in JBoss 5, where can I find a decent description of how it works?

      Would it resolve the problem if I could somehow delegate the loading of the remote interface to the default classloader, so that that single class would not be isolated? Is it possible to do that?

       

      Regards,

      Miklos Balazs

        • 1. Re: EJB's and classloading
          alesj
          If this is specific to the new classloading model in JBoss 5, where can I find a decent description of how it works?

          * http://java.dzone.com/articles/jboss-microcontainer-classloading

           

          Would it resolve the problem if I could somehow delegate the loading of the remote interface to the default classloader, so that that single class would not be isolated? Is it possible to do that?

          You can simply switch the location of that MBean class to Service.ear.

          And the isolated Application.ear would still find it.

           

          Application.ear' parent domain would be default domain,

          which would then also own Service.ear,

          hence it would find Service.ear' classes, aka that MBean.

          • 2. Re: EJB's and classloading
            mbalazs

            Hi Ales,

             

            Thanks for your answer!


            Would it resolve the problem if I could somehow delegate the loading of the remote interface to the default classloader, so that that single class would not be isolated? Is it possible to do that?

            You can simply switch the location of that MBean class to Service.ear.

            And the isolated Application.ear would still find it.

             

            The MBean class is already in Service.ear, and the Application.ear has no problem accessing it. The problem is that when the MBean calls back to the application, the application's code needs to access an EJB. And that call is originated from the MBean, thus from Service.ear's domain. And the EJB's remote interface is in Application.ear, which can't be seen from Service.ear's domain. And I don't want to move classes, these two deployments are separated for a reason.

             

            One solution that came to my mind would be two put the EJB's classes in the lib/ of the application server instance, thus it would be available for all classloaders. But that's not good because I need the EJB's to be hot-deployable. And the application archive contains some Seam and Portlet Bridge libraries that need to be isolated. Putting the EJB to another root deployment would also work, but I wouldn't want that either, if it's possible to do otherwise. I think now I start to see it clearer .

             

            Now I think the question is: how can I define classloading isolation in application.ear on a per-library basis. So that I can isolate the Seam libraries and stuff, but not the EJB's. This would resolve this situation, am I right?

             

            Regards,

            Miklos

            • 3. Re: EJB's and classloading
              alesj

              Ah, I see I read the thing too fast. :-)

               

              This is a classic problem of remote EJB invocation.

              You could bundle the interface in both ear', and somehow make the Service.ear call a call-by-value.

              (dunno if we support such fine-grained configuration)

               

              Or we could go down the big-ball-o-mud path, imho a cool JBoss feature. :-)

              Now I think the question is: how can I define classloading isolation in application.ear on a per-library basis. So that I can isolate the Seam libraries and stuff, but not the EJB's. This would resolve this situation, am I right?

              I should be doable, yes.

              Let me think about this, and get back to you.

              • 4. Re: EJB's and classloading
                alesj
                Now I think the question is: how can I define classloading isolation in application.ear on a per-library basis. So that I can isolate the Seam libraries and stuff, but not the EJB's. This would resolve this situation, am I right?

                I should be doable, yes.

                Let me think about this, and get back to you.

                There is a excludedExportPackages string and excludedExport filter on ClassLoadingMetaData -- class representation of jboss-classloading.xml.

                As you can deduct from the name, it's unfortunately just the other way around as we need it, it lists excludes instead of includes.

                 

                Unless you can somehow list all excludes (all, but that mbean' package name),

                you will need to hack this thing programmatically (otherwise you could use jboss-classloading.xml),

                meaning you will have to implement a deployer which creates proper ClassLoadingMetaData instance,

                and attaches it to App.ear' DeploymentUnit instance.

                • 5. Re: EJB's and classloading
                  mbalazs

                  Hi Ales,

                   

                  Thanks for your reply. I think that being able to specify both inclusions and exclusions in classloading isolation would be a nice feature BTW.

                   

                  Regards,

                  Miklós

                  • 6. Re: EJB's and classloading
                    alesj
                    I think that being able to specify both inclusions and exclusions in classloading isolation would be a nice feature BTW.

                    Yeah, was thinking of the same,

                    specially since we already have include vs. exclude,

                    but no includeExports vs. excludeExports.

                     

                    I'll put it on my TODO list.

                    Or you can provide me with a patch - core code change + test(s). ;-)