7 Replies Latest reply on Feb 2, 2011 9:55 AM by jhutton

    [AS6] EJB injection failed: classloaders are not equal

    thomas.kriechbaum

      Hello,

       

      when injecting an EJB from an other EAR I'm getting an IllegalArgumentException containing the message

       

      failed to set value org.jnp.interfaces.NamingContext@1fd1301 
         on field private org.foo.ticket.TicketService 
         org.foo.business.BusinessServiceBean.ticketService; 
         Reason: ClassLoaders of value: 
         BaseClassLoader@1d48043{path-to-server/default/conf/jboss-service.xml} and 
         target field BaseClassLoader@170a4fb{path-to-server/default/deploy/business-ear-1.0.0.ear} 
         are not equal
      

       

      The ticket-ear contains the TicketService EJB that is published with the global JNDI name

       

      TicketService - EJB3.x Default Remote Business Interface
      ticket-ear-1.0.0/TicketServiceBean/remote-org.foo.ticket.TicketService - EJB3.x Remote Business Interface
      

       

       

      Within the business-ear the TicketService EJB is referenced by the following code

       

      @Stateless
      public class BusinessServiceBean implements BusinessService {
      
                @EJB(mappedName="ticket-ear-1.0.0/TicketServiceBean")
                private TicketService ticketService;
      
              ...
      }
      
      

       

      The business-ear only holds the EJBs remote client view (TicketService class and Ticket class) in a separate JAR (not the whole ticket-service-ejb.jar that is part of the ticket-ear).

       

       

      Do I have to apply some special classloader/classpath settings?

      Do I have to follow some kind of patterns when referencing an EJB from another EAR?

       

      Thanks,

      Thomas

        • 1. Re: [AS6] EJB injection failed: classloaders are not equal
          jaikiran

          Try setting callByValue property of RemoteNamingBean to true in JBOSS_HOME/server/<servername>/deploy/naming-jboss-beans.xml:

           

          <bean name="RemoteNamingBean" class="org.jnp.server.Main">
                  ...
          
                  <!-- The call by value mode. true if all lookups are unmarshalled using
                      the caller's TCL, false if in VM lookups return the value by reference. -->
                  <property name="callByValue">true</property>
          ...
          
          • 2. [AS6] EJB injection failed: classloaders are not equal
            thomas.kriechbaum

            I have set <property name="callByValue">true</property> , but I'm still getting the same exception as described above.

            • 3. [AS6] EJB injection failed: classloaders are not equal
              jhutton

              Hi Thomas,

               

              I encountered a similar problem today, where injection of resources (jms) into an EJB gave the same "Classloaders of value: BaseClassLoader...", etc. I tried doing jndi lookups for the resources, and got nonsensical ClassCastExceptions, because the resource implemented the interface.

               

              It turned out to be that I was including the jms.jar in my war file, and JBoss's class loader will, by default, prefer local or child versions (where the parent is the container's class loader) of a class over remote ones. That causes the situation where com.acme.Foo != com.acme.Foo (because they're from different class loaders) and unexpected ClassCastExceptions occur. There is lots of information on JBoss class loading here, http://community.jboss.org/wiki/JBossClassLoaderIntroduction.

               

              Anyway, in my situation, simply making the jms jar <scope>provided</scope> fixed the issue. I'm guessing something similar is happening here.

               

              Hope that helps,

              Jesse

              • 4. Re: [AS6] EJB injection failed: classloaders are not equal
                thomas.kriechbaum

                In my projects, I have defined javax.ejb::ejb-api with scope provided.

                 

                Maybe I have a conceptional missunderstanding of JEE components. To get my JEE universe back to balance, I have attached the maven project, the EARs and a soap-ui test. As described above, the sample covers a simple EJB injection scenario. The exception is thrown not during deployment, but when the WS gets invoked.

                 

                Could anyone be so kind and try to deploy the EARs - or have a look at my maven projects.

                 

                Thanks,

                Thomas

                • 5. Re: [AS6] EJB injection failed: classloaders are not equal
                  jhutton

                  Hi Thomas,

                   

                  I took a quick look at your uploaded packages, and you're including the ticket-service-1.0.0.jar file in both ticket-ear-1.0.0.ear and business-ear-1.0.0.ear. So, when your BusinessServiceBean is created by the EJB container (when your web service is invoked), it tries to inject a TicketServiceBean from your ticket-ear-1.0.0.ear package into the bean's member 'ticketService' variable, which uses the TicketService interface. The problem is that TicketServiceBean being injected comes from a different classloader than the TicketService interface that it's being inject into (because of JBoss's classloading strategy). If you remove the @EJB annotation and instead use jndi to look up the EJB, you'll se a class cast exception, for the same reason.

                   

                  If you make sure that ticket-service.jar is not included in the business-ear, it should work.

                   

                  Jesse

                  • 6. Re: [AS6] EJB injection failed: classloaders are not equal
                    thomas.kriechbaum

                    Hello Jesse,

                     

                    I have tested the following scenarios:

                     

                    1.) business-ear without ticket-service.jar (contains remote interface of referenced EJB).

                    In this case I get a java.lang.NoClassDefFoundError: Lorg/samples/ticket/TicketService when the EAR gets deployed

                     

                     

                    2.) Then I have also adopted the Class-Path entry in business-core.jar/META-INF/MANIFEST.MF (business-core.jar contains the EJB implementation that references the TicketService EJB).

                    changed from Class-Path: ticket-service-1.0.0.jar business-service-1.0.0.jar to Class-Path: business-service-1.0.0.jar

                    Same result as in 1.

                     

                    I think, I have to do more reading on JBossAS classloader strategy. Currently my experience is based on IBM WAS. But I thought, that this kind of packaging is conform to JEE standards.

                     

                    Thomas

                    • 7. Re: [AS6] EJB injection failed: classloaders are not equal
                      jhutton

                      Thomas,

                       

                      What if you place the ticket-service.jar in the lib folder of your server ($JBOSS_HOME/server/xxxx/lib/)? That should take care of the NoClassDefFoundError you get when deploying business-ear.

                       

                      Jesse