7 Replies Latest reply on Sep 25, 2008 3:02 AM by avogt_sundn

    No ClassLoaders found using derived class

    fabboco

      Hi,

      I need to store different contents in the same EJB3 container as shows in the following code.

      @Entity
      @Table(name = "wk_container")
      public class Container implements Serializable
      {
       Long id;
       String containerName;
      
       Content content;
      
       @Id
       @GeneratedValue(strategy=GenerationType.AUTO)
       public Long getId()
       {
       return id;
       }
      
       public void setId(Long id)
       {
       this.id = id;
       }
      
       public String getContainerName()
       {
       return containerName;
       }
      
       public void setContainerName(String containerName)
       {
       this.containerName = containerName;
       }
      
       public Content getContent()
       {
       return content;
       }
      
       public void setContent(Content content)
       {
       this.content = content;
       }
      
      }
      
      public class Content implements java.io.Serializable
      {
       String info1;
       Long info2;
      
       public String getInfo1()
       {
       return info1;
       }
      
       public void setInfo1(String info1)
       {
       this.info1 = info1;
       }
      
       public Long getInfo2()
       {
       return info2;
       }
      
       public void setInfo2(Long info2)
       {
       this.info2 = info2;
       }
      
       public void function()
       {}
      }
      
      


      Container and Content are packaged into a single .jar and deployed into jboss.


      My client rich client is

       ........
       ctx = new InitialContext(props);
      
       ContainerManager contManager = (ContainerManager) ctx.lookup("ContainerBean/remote");
      
       Container container1 = new Container();
       Container container2 = new Container();
      
       Content content = new Content();
      
       content.setInfo1("string info");
       content.setInfo2(new Long(1));
      
       container1.setContainerName("container 1");
       container1.setContent(content);
       container1 = contManager.merge(container1);
      
      
       DerivedContent derivedContent = new DerivedContent();
      
       derivedContent.setInfo1("string info");
       derivedContent.setInfo2(new Long(2));
      
       container2.setContainerName("container 2");
       container2.setContent(derivedContent);
      
       container2 = contManager.merge(container2);
       ........
      


      DerivedContent is:

      public class DerivedContent extends Content implements Serializable
      {
       public DerivedContent()
       {
       super();
       }
      
       @Override
       public void function()
       {
       System.out.println("DerivedContent function");
       }
      }
      


      When I try to merge the container2 that includes the DerivedContent instance I get the following error:

      Exception in thread "main" java.lang.RuntimeException: java.lang.ClassNotFoundException: No ClassLoaders found for: testworkflowhandlers.client.DerivedContent (no security manager: RMI class loader disabled)
       at org.jboss.aop.joinpoint.MethodInvocation.getArguments(MethodInvocation.java:227)
       at org.jboss.ejb3.stateless.StatelessContainer.dynamicInvoke(StatelessContainer.java:216)
       at org.jboss.aop.Dispatcher.invoke(Dispatcher.java:107)
       at org.jboss.aspects.remoting.AOPRemotingInvocationHandler.invoke(AOPRemotingInvocationHandler.java:82)
       at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:580)
       at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:450)
       at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:290)
       at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:344)
       at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:202)
      Caused by: java.lang.ClassNotFoundException: No ClassLoaders found for: testworkflowhandlers.client.DerivedContent (no security manager: RMI class loader disabled)
       at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:371)
       at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
       at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
       at org.jboss.system.JBossRMIClassLoader.loadClass(JBossRMIClassLoader.java:79)
       at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
       at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
       at java.io.ObjectInputStream.readNonProxyDesc(ObjectInputStream.java:1538)
       at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1460)
       at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1693)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
       at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1912)
       at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1836)
       at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1713)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
       at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1628)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1293)
       at java.io.ObjectInputStream.readObject(ObjectInputStream.java:339)
       at java.rmi.MarshalledObject.get(MarshalledObject.java:135)
       at org.jboss.aop.joinpoint.MethodInvocation.getArguments(MethodInvocation.java:219)
       ... 8 more
      

      The ContainerManager is:

      @Stateless
      @Remote(ContainerManager.class)
      public class ContainerBean implements ContainerManager
      {
       @PersistenceContext(unitName="Workflow")
       private EntityManager manager;
      
       public void persist(Container container)
       {
       manager.persist(container);
       }
      
       public Container merge(Container container)
       {
       return manager.merge(container);
       }
      
       public Container find(Long id)
       {
       return manager.find(Container.class, id);
       }
      
       public void remove(Container container)
       {
       manager.remove(container);
       }
      
      }
      


      It seams to me that the ContainerBean is not able to load DerivedContent since it is not into the deployed jar.

      Shouldn't DerivedContent transferred by the RMI protocol ?

      I can't put DerivedContent into the jar file since the Container should be a generic manger for different contents and only the client application should know about it.

      Can anyone give me any suggestion ?

      Thanks

      Fabrizio



      PS: My environment is

      * jboss-4.0.3SP1
      * jboss-EJB-3.0_RC5-PFD




        • 1. Re: No ClassLoaders found using derived class
          bill.burke

          We do not use RMI. It is too inefficient.

          JBoss Remoting does support class imports, BUT...things like arguments need to be unmarshalled by the classloader of the EJB container. So, we defer the unmarshalling until the EJB container has had a chance to set the correct classloader.

          So, we will not be supporting this usage.

          • 2. Re: No ClassLoaders found using derived class
            redijedi

            Has JBoss' stance here changed? I've got a similar problem. I have a remote SLSB that takes Object instances and stores them in a cache - that's the plan anyway. Unfortunately, whenever I pass in any object implementation I receive the same error. Seems to me that this is not expected behavior since it is reasonable to suspect that if a method accepts some object Foo, then it should accept any FooImplementingOrExtending object. I think that's one of the tenants of OOP, no?

            • 3. Re: No ClassLoaders found using derived class
              jaikiran

              Can you please post your code, the exception stacktrace and also the JBoss and Java version you are using? Also, where are you calling the bean from?

              Unfortunately, whenever I pass in any object implementation I receive the same error


              Is this object implementation present in any of your jar files? Please provide more details about your application packaging.



              • 4. Re: No ClassLoaders found using derived class
                redijedi

                I'll throw together a test app to demonstrate in a bit as my project is quite large and proprietary. However, you mentioned part of the problem: my ejb does not have the implementation on the classpath. But that is sort of the point of the system. I'm trying to get it to just take Objects - any Objects. I don't want to do anything with them accept store them in a cache which itself doesn't care about implementations either.

                The problem, it appears, is that JBoss does care about implementations. I want to work with any Object, but JBoss appears to require certain types, specifically those defined in the interface and not their subclasses. That's what's causing my problem.

                • 5. Re: No ClassLoaders found using derived class
                  jaikiran

                   

                  "redijedi" wrote:
                  However, you mentioned part of the problem: my ejb does not have the implementation on the classpath. But that is sort of the point of the system. I'm trying to get it to just take Objects - any Objects. I don't want to do anything with them accept store them in a cache which itself doesn't care about implementations either.



                  Okay. The reason i asked you about this was to ensure that this was not of those usual ClassNotFound issues :-)


                  • 6. Re: No ClassLoaders found using derived class
                    alrubinger

                    We're getting compile-time and runtime requirements mixed here.

                    Yes, it's a valid tenant of OOP to accept any subclass of Object in your cache.

                    However, for the JVM to work with objects, it must first load the Class that defines it, meaning the .class definition must be available to the ClassLoader. In the case of EJB3, each "Container" has its own ClassLoader (allocated at deployment/container construction), and this CL does not support loading bytes from a remote location (which would be required for this use case).

                    So long story short is that all class definitions must be available on the server for them to use used.

                    S,
                    ALR

                    • 7. Re: No ClassLoaders found using derived class
                      avogt_sundn

                      Hi

                      is that really true:

                      and this CL does not support loading bytes from a remote location (which would be required for this use case).


                      I tried to lookup an session bean from which i only have one @Remote interface in my class loader (ie. in the ear or in the unit test runner). That session bean implements other @Remote interfaces. But i dont care for them. My code is like the user of the factory pattern: InitialContext().lookup() ist the factory, i get an session bean, i communicate with it across the one @Remote interface known to me.

                      Reason why the other @Remote interface needs to be loaded is that the deserialized statelessproxystub references it in its internals.

                      When I activate remote class loading ... i can see that the referenced session bean interfaces get remotely downloaded... but they are not available for the container that hosts the referencing session bean.