4 Replies Latest reply on Sep 24, 2010 1:23 AM by lordpraveen

    JBoss-classloading.xml in EAR /EJB

    lordpraveen

      Hi ,

       

      I have an EAR which I deploy in jboss-5.1.0.

       

      A.EAR

          |----lib/x.jar

          |----EJB1.jar

          |----EJB2.jar

       

      I wanted to just expose the interfaces from the EJB's, hence I have jboss-classloading.xml in both EJB1.jar and EJB2.jar.

      What I was hoping to achieve is that just have the interfaces exposed in my EJB's to other EJB's in the same EAR and also to other EAR's in AS.

       

      EJB1.jar

          |-----------com.ejb1.interface.EJB1Intf / EJB1IntfLocal extends EJB1Intf / EJB1IntfRemote extends EJB1Intf

          |-----------com.ejb1.implementation.EJB1Bean implements EJB1IntfLocal,EJB1IntfRemote.

          |-----------META-INF/jboss-classloading.xml

       

      <classloading xmlns="urn:jboss:classloading:1.0" domain="A.EAR-0.0.1-SNAPSHOT-exploded.ear" parent-domain="DefaultDomain"
          export-all="NON_EMPTY" import-all="true" excluded="META-INF">
          <capabilities>
              <package name="com.ejb1.interface" />
          </capabilities>
      </classloading>

       

      Similarly for EJB2.jar.

       

      This is how my jmx-console looks like:

      jboss.classloader

       

      EJB1 calls EJB2 via JNDI.

       

      EJB1Bean:

      public boolean callTheOtheEJB() {
          EJB2Intf myStateless = lookup(EJB2Intf.class, "service/EJB2IntfBean");
          logger.info("Called myStateless sayHello = "+  myStateless.sayHello());
           return true;
          }

       

      EJB2Bean:

      public String sayHello(){
           return "Hello"
      }
      

       

      My Client:

      Properties props = new Properties();
          props.put(InitialContext.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");
          props.put(InitialContext.PROVIDER_URL, "jnp://127.0.0.1:1099");
          try {
              InitialContext jndiContext = new InitialContext(props);
              Object obj = jndiContext.lookup("AEAR-0.0.1-SNAPSHOT-exploded/EJB1Bean/remote");
              System.out.println(obj.getClass());
              EJB1Intf callingEJBIntf = (EJB1Intf)obj;
              callingEJBIntf.callTheOtheEJB();
      
          } catch (NamingException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
      

       

      Problem: EJB1 cant see EJB2Intf.

       

      Caused by: java.lang.ClassNotFoundException: com.ejb2.interface.EJB2Intf from BaseClassLoader@1f9c621d{VFSClassLoaderPolicy@53ed6e21{name=vfszip:/jboss-5.1.0.GA/server/default/deploy/AEAR-0.0.1-SNAPSHOT-exploded.ear/EJB1.jar/ domain=ClassLoaderDomain@b901239{name=AEAR-0.0.1-SNAPSHOT-exploded.ear parentPolicy=BEFORE parent=ClassLoaderDomain@7a0aae8a{DefaultDomain}} roots=[DelegatingHandler@148464531[path=AEAR-0.0.1-SNAPSHOT-exploded.ear/EJB1.jar context=file:/jboss-5.1.0.GA/server/default/deploy/ real=file:/jboss-5.1.0.GA/server/default/deploy/AEAR-0.0.1-SNAPSHOT-exploded.ear/EJB1.jar]]  delegates=null exported=[com.ejb1.interface]NON_EMPTY}}

       

      They are part of the same ClassLoaderDomain.

       

      When I do listExportingClassloader() for AEAR domain,

      {com.ejb1.interface=[jboss.classloader:id="vfszip:/jboss-5.1.0.GA/server/default/deploy/
      AEAR-0.0.1-SNAPSHOT-exploded.ear/EJB1-SNAPSHOT.jar/"],
      com.ejb2.interface=[jboss.classloader:id="vfszip:/jboss-5.1.0.GA/server/default/deploy/
      AEAR-0.0.1-SNAPSHOT-exploded.ear/EJB2-SNAPSHOT.jar/"]}

       

       

      Can anyone help? I am not sure where I am going wrong.

        • 1. Re: JBoss-classloading.xml in EAR /EJB
          alesj

          Can you try to mock up this a bit easier?

          (try doing/hacking on top of my MC demos - http://anonsvn.jboss.org/repos/jbossas/projects/demos/microcontainer/trunk/)

          * two jars mocking your ejb jars

          * third jar containing a service that would call a service from the first jar

           

          The jboss-classloading.xml looks a bit wrong, but I doubt that's the real cause.

          e.g. export-all=NON_EMTPY vs. capabilities, no need to declare parent-domain as default (that is done by default already)

          • 2. Re: JBoss-classloading.xml in EAR /EJB
            lordpraveen

            Hi Ales,

             

            Before the EAR usecase, I tried deploying just the jars and it worked like a charm. The moment I bundle the same jarr/ejb's in an EAR, I cant seem to acheive the desired result.

             

            The usecase I tried:

            EJB1.jar, EJB2.jar and x.jar all in the jboss deploy folder.

             

            Same settings as above.

            EJB1.jar and EJB2.jar just expose the interface. EJB1 looks up EJB2 via JNDI as above.

             

            and it worked.

            EJB1 could only see the exposed EJB2 interface.

             

            This same usecase doesnt work when I bundle all the EJB's and the lib jars in an EAR.

            EJB1 has access to all classes in EJB1.

            • 3. Re: JBoss-classloading.xml in EAR /EJB
              alesj
              This same usecase doesnt work when I bundle all the EJB's and the lib jars in an EAR.

              EJB1 has access to all classes in EJB1.

              Strange. Must be some config detail that we're both missing.

               

              Debugging this would probably / eventually expose it, but the MC CL layer is quite complex,

              so it would take time to get a grasp of it. But nobody is stopping you. ;-)

              • 4. Re: JBoss-classloading.xml in EAR /EJB
                lordpraveen

                Hi  Ales,

                I checked  org.jboss.deployers.plugins.classloading.AbstractClassLoaderDescribeDeployer.

                 

                if (deployment.isTopLevelClassLoader() == false)
                {
                     if (deployment.getParentDomain() == null) {
                            deployment.setDomain(unitName);
                            log.debugf("Will use synthetic domain for classloader of subdeployment: %1s", unitName);
                     }else{
                             log.debugf("Will create top level classloader for subdeployment: %1s", unitName);
                     }
                  }

                 

                If an EJB (with jboss-classloading.xml) is bundled within the EAR file , there is a need to specify just the parent-domain and not the domain.

                 

                <classloading xmlns="urn:jboss:classloading:1.0" parent-domain="DefaultDomain"
                    export-all="NON_EMPTY" import-all="true" excluded="META-INF">
                    <capabilities>
                        <package name="com.ejb1.interface" />
                    </capabilities>
                </classloading>

                 

                That  solved my EAR usecase.