8 Replies Latest reply on Jul 3, 2008 4:18 PM by Ron Sigal

    ClassNotFoundException while calling remote ejb3 across isol

    Armin Vogt Newbie

      Using JBoss Portal 2.6.4 with JDK1.5.0

      It seems to me that RMI class loading does not work with my configuration
      I gave a security policy to the jboss to allow for RMI class loading.
      And i gave the loaderport parameter to the DefaultEjb3Connector as described here [URL]http://www.jboss.com/index.html?module=bb&op=viewtopic&t=126930[/URL]

       <mbean code="org.jboss.remoting.transport.Connector"
       name="jboss.remoting:type=Connector,name=DefaultEjb3Connector,handler=ejb3">
       <depends>jboss.aop:service=AspectDeployer</depends>
       <!--attribute name="InvokerLocator">socket://${jboss.bind.address}:3873/?loaderport=4873</attribute-->
      
       <attribute name="Configuration">
       <config>
       <invoker transport="socket">
       <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
       <attribute name="serverBindPort">3873</attribute>
       <attribute name="numAcceptThreads">1</attribute>
       <attribute name="maxPoolSize">300</attribute>
       <attribute name="clientMaxPoolSize" isParam="true">50</attribute>
       <attribute name="timeout" isParam="true">60000</attribute>
       <attribute name="loaderport" isParam="true">4873</attribute>
       <attribute name="serializationtype" isParam="true">jboss</attribute>
       <attribute name="byvalue" isParam="true">true</attribute>
       <attribute name="force_remote" isParam="true">true</attribute>
       </invoker>
       <handlers>
       <handler subsystem="AOP">org.jboss.aspects.remoting.AOPRemotingInvocationHandler</handler>
       </handlers>
       </config>
      
       </attribute>
       </mbean>
      


      I get a ClassNotFoundException for the implementing ejb class of the method parameter, but I expected the class to be loaded via RMI loader (via WebService on localhost:8083). Is there something else that I need to configure?

      Caused by: java.lang.ClassNotFoundException: palmyra.baustein.geschaeftsverwaltung.antrag.ProtokollVBeanEjb
       at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
       at java.security.AccessController.doPrivileged(Native Method)
       at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
       at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
       at java.lang.Class.forName0(Native Method)
       at java.lang.Class.forName(Class.java:242)
       at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:430)
       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:91)
       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:1544)
       at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1466)
       at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1699)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
       at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1634)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
       at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
       at java.rmi.MarshalledObject.get(MarshalledObject.java:135)
       at org.jboss.aop.joinpoint.MethodInvocation.getArguments(MethodInvocation.java:267)
      


      Let me explain the overall situation.
      Consider this: one ejb A gets another ejb B injected via @EJB annotation.
      ejb A is thus owning a proxy to ejb B.
      the respective classes are deployed in two ears that are isolated ie. have their own class loader repositories declared in jboss-app.xml
      In order to call methods on B, the ear with ejb A contains the ejb interface and parameter classes of ejb B.

      Now while there is no problem ejb A calling methods on ejb B, B cannot call on A vice versa, because the ear of ejb B does not contain the classes of ejb A.
      But I want ejb B to be able to callback its owning ejb A. I therefore transmitted the proxy of ejb A to ejb B.

      class EjbB {
       public void setOwner(MyCommonInterface bean) { .. }
      


      class MyInterceptor{
       @Resource
       SessionContext sessionContext;
       void propagateOwner() {
       iface = sessionContext.getInvokedBusinessInterface();
       MyCommonInterface owner = (MyCommonInterface)
       sessionContext.getBusinessObject(iface);
       EventListener listener = (EventListener) new InitialContext() .lookup("my-ear/EventListenerEjb/remote");
       owner.setEventListener(listener);
       // the next line throw ClassNotFoundException
       listener.setReceiver(vbean);
      
      


      14:14:39,978 ERROR [VBeanInterceptor] VBean: palmyra.baustein.geschaeftsverwaltung.antrag.ProtokollVBeanEjb@d213c: java.lang.Runti
      meException: java.lang.ClassNotFoundException: palmyra.baustein.geschaeftsverwaltung.antrag.ProtokollVBeanEjb java.lang.ClassNotFo
      undException: palmyra.baustein.geschaeftsverwaltung.antrag.ProtokollVBeanEjb
      java.lang.RuntimeException: java.lang.ClassNotFoundException: palmyra.baustein.geschaeftsverwaltung.antrag.ProtokollVBeanEjb
       at org.jboss.aop.joinpoint.MethodInvocation.getArguments(MethodInvocation.java:276)
       at org.jboss.ejb3.stateful.StatefulContainer.dynamicInvoke(StatefulContainer.java:328)
       at org.jboss.ejb3.remoting.IsLocalInterceptor.invokeLocal(IsLocalInterceptor.java:81)
       at org.jboss.ejb3.remoting.IsLocalInterceptor.invoke(IsLocalInterceptor.java:72)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.stateful.StatefulRemoteProxy.invoke(StatefulRemoteProxy.java:139)
       at $Proxy400.setReceiver(Unknown Source)
       at palmyra.core.vorgangssteuerung.interceptor.VBeanInterceptor.doEJBAnnotation(VBeanInterceptor.java:125)
       at palmyra.core.vorgangssteuerung.interceptor.VBeanInterceptor.postConstruct(VBeanInterceptor.java:97)
      


      Caused by: java.lang.ClassNotFoundException: palmyra.baustein.geschaeftsverwaltung.antrag.ProtokollVBeanEjb
       at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
       at java.security.AccessController.doPrivileged(Native Method)
       at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
       at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
       at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
       at java.lang.Class.forName0(Native Method)
       at java.lang.Class.forName(Class.java:242)
       at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:430)
       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:91)
       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:1544)
       at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1466)
       at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1699)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
       at java.io.ObjectInputStream.readArray(ObjectInputStream.java:1634)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1299)
       at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
       at java.rmi.MarshalledObject.get(MarshalledObject.java:135)
       at org.jboss.aop.joinpoint.MethodInvocation.getArguments(MethodInvocation.java:267)
      




        • 1. Re: ClassNotFoundException while calling remote ejb3 across
          Armin Vogt Newbie

          Ok, i found that the reason actually was my using isolated ears with dedicated loader repositores, enabled in the jboss-app.xml

          <!DOCTYPE jboss-app
           PUBLIC "-//JBoss//DTD J2EE Application 1.4//EN"
           "http://www.jboss.org/j2ee/dtd/jboss-app_4_2.dtd">
          <jboss-app>
           <loader-repository>
           palmyra-bsp-bestandsdaten-1.0:loader=bsp-bestandsdaten-1.0.EAR
           <loader-repository-config>
           java2ParentDelegation=true
           </loader-repository-config>
           </loader-repository>
          </jboss-app>


          Once I empty the jboss-app.xml, everything works fine.

          Is there a way to have my isolated ear serve its classes for remote class loading?

          • 2. Re: ClassNotFoundException while calling remote ejb3 across
            Ron Sigal Master

            I've fixed this issue for Remoting release 2.2.2.SP8.

            org.jboss.remoting.marshal.MarshallerLoaderHandler, which is the ServerInvocationHandler for the classloader Connector, now is able to search org.jboss.mx.loading.HeirarchicalLoaderRepository3s, which allows it to find scoped classes. In order to make it possible to inform the MarshallerLoaderHandler about the HeirarchicalLoaderRepository3s to be searched, a section has been added to the MBean Connector definition. This section should be added to the Connector for which the "loaderport" parameter is defined. A client connected to such a Connector will be able to connect to the associated classloader Connector and download classes from any of the repositories listed in the section.

            For example, to allow an EJB3 to get scoped classes in an EAR where the jboss-app.xml is

             <!DOCTYPE jboss-app PUBLIC "-//JBoss//DTD J2EE Application 1.4//EN" "http://www.jboss.org/j2ee/dtd/jboss-app_4_0.dtd">
             <jboss-app>
             <loader-repository>jboss.remoting:loader=titan.ear</loader-repository>
             </jboss-app>
            


            the EJB3 Connector should look something like the following:

             <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>
             <invoker transport="socket">
             <attribute name="serverBindAddress">${jboss.bind.address}</attribute>
             <attribute name="serverBindPort">3873</attribute>
             <attribute name="loaderport" isParam="true">3883</attribute>
             </invoker>
            
             <repositories>
             <repository>jboss.remoting:loader=titan.ear</repository>
             </repositories>
            
             <handlers>
             <handler subsystem="AOP">org.jboss.aspects.remoting.AOPRemotingInvocationHandler</handler>
             </handlers>
             </config>
             </attribute>
             </mbean>
            


            That is, the classloader Connector is informed about the HeirarchicalLoaderRepository3 with ObjectName "jboss.remoting:loader=titan.ear".

            An example case is attached to JBREM-962 "Remote classloading does not work with Isolated EARs".

            • 3. Re: ClassNotFoundException while calling remote ejb3 across
              Armin Vogt Newbie

              Thank you, Ron.

              Yet, one thing remains, perhaps based on my missconception:

              I took your ScopedTest and changed according to my use case:
              TravelAgentBean now implements another @Remote interface, namely SpecialTravelAgent. This interface is not available in the clients class loader.

              When the client now does a lookup, he gets a remoteproxystub, but cannot use it because that other business interface ist not being loaded from the remote class loader.

              This is my case: i want to use an ejb that has one remote interface know to the client, but has various other remote interfaces NOT KNOWN to the client.
              Is that possible?

              Just add some interface SpecialTravelAgent to the deployment, BUT not to the client.jar!

              The exception in the Client.java then is

              javax.naming.CommunicationException [Root exception is java.lang.ClassNotFoundException: com.titan.travelagent.SpecialTravelAgent]
               at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:786)
               at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:627)
               at javax.naming.InitialContext.lookup(InitialContext.java:351)
               at com.titan.client.Client.testScoped1(Client.java:46)
               at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
               at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
               at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
               at java.lang.reflect.Method.invoke(Method.java:585)
               at junit.framework.TestCase.runTest(TestCase.java:154)
               at junit.framework.TestCase.runBare(TestCase.java:127)
               at junit.framework.TestResult$1.protect(TestResult.java:106)
               at junit.framework.TestResult.runProtected(TestResult.java:124)
               at junit.framework.TestResult.run(TestResult.java:109)
               at junit.framework.TestCase.run(TestCase.java:118)
               at junit.framework.TestSuite.runTest(TestSuite.java:208)
               at junit.framework.TestSuite.run(TestSuite.java:203)
               at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
               at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
               at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
               at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
               at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
               at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
              Caused by: java.lang.ClassNotFoundException: com.titan.travelagent.SpecialTravelAgent
               at java.net.URLClassLoader$1.run(URLClassLoader.java:200)
               at java.security.AccessController.doPrivileged(Native Method)
               at java.net.URLClassLoader.findClass(URLClassLoader.java:188)
               at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
               at java.lang.ClassLoader.loadClass(ClassLoader.java:251)
               at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319)
               at java.lang.Class.forName0(Native Method)
               at java.lang.Class.forName(Class.java:242)
               at sun.rmi.server.LoaderHandler.loadProxyInterfaces(LoaderHandler.java:707)
               at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:651)
               at sun.rmi.server.LoaderHandler.loadProxyClass(LoaderHandler.java:588)
               at java.rmi.server.RMIClassLoader$2.loadProxyClass(RMIClassLoader.java:628)
               at java.rmi.server.RMIClassLoader.loadProxyClass(RMIClassLoader.java:294)
               at sun.rmi.server.MarshalInputStream.resolveProxyClass(MarshalInputStream.java:238)
               at java.io.ObjectInputStream.readProxyDesc(ObjectInputStream.java:1500)
               at java.io.ObjectInputStream.readClassDesc(ObjectInputStream.java:1463)
               at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1699)
               at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
               at java.io.ObjectInputStream.readObject(ObjectInputStream.java:348)
               at java.rmi.MarshalledObject.get(MarshalledObject.java:135)
               at org.jnp.interfaces.MarshalledValuePair.get(MarshalledValuePair.java:72)
               at org.jnp.interfaces.NamingContext.lookup(NamingContext.java:710)
               ... 21 more
              
              
              


              • 4. Re: ClassNotFoundException while calling remote ejb3 across
                Ron Sigal Master

                If I understand correctly, what you're asking for isn't going to be solved in Remoting. The Remoting remote classloading facility is used only to unmarshal classes coming from the server.

                But you're up against Java typing. To be able to use an interface, you would need to refer to it in your client code. That means that the interface would have to be available to the classloader that loads your client. In your case, the client is an EJB3, and by doing scoping you're specifically preventing your client code from seeing the other EJB3's repository.

                So, as I understand the situation, I don't think you could do what you want to do. Of course, someone who knows more about this subject might have a better answer. You could try posing the question on the "Installation, Configuration & DEPLOYMENT" forum (http://www.jboss.com/index.html?module=bb&op=viewforum&f=61).

                • 5. Re: ClassNotFoundException while calling remote ejb3 across
                  Armin Vogt Newbie

                  let me explain my situation:

                  i'd like to have ejb behave polymorphic like with plain java classes. I know ONE interface of my ejbs but not ALL - and i don't need to know them all.

                  All my ejbs implement one common remote interface. I create ejb instances with a lookup and assign the ejb proxy to a variable typed with that know interface.

                  Now enters the org.jboss.ejb3.stateful.StatefulRemoteProxy that gets unmarshalled in my ear. That object references all the other remote interfaces of that ejb thus forcing a class loading of these interfaces - which is why i have to supply all these interfaces although i don't use them in code.

                  As you can see, I dont really want these interfaces to be downloaded anyway.
                  Its only for the sake of the StatefulRemoteProxy instance. There would be no need to download any classes remotely, because i have the known interface and the known parameter types included in each ear .

                  What breaks my architecture is the needs of the StatefulRemoteProxy.

                  Without this i cannot build a factory that is able to instantiate ejbs deployed in other isolated ears.

                  Perhaps there is some completely other way I cannot think of ?

                  • 6. Re: ClassNotFoundException while calling remote ejb3 across
                    Ron Sigal Master

                    Ok. It sounds like I misunderstood when I thought you wanted to reference the unknown interfaces *in your code*. The problem is occurring before you even get there, in the JNDI lookup, right?

                    It looks like the JNDI lookup is using RMI, so it seems like you want to enable RMI dynamic classloading. In fact, the Application Server has a WebService MBean that supports RMI dynamic classloading. See, for example, the JBoss 4 Application Server Guide "Section 10.6. RMI Dynamic Class Loading" at http://docs.jboss.org/jbossas/jboss4guide/r5/html/. The WebService MBean is configured in ${JBOSS_HOME}/server/${CONFIG}/conf/jboss-service.xml.

                    Note that to enable RMI dynamic classloading you have to install an RMISecurityManager:

                    System.setSecurityManager(new RMISecurityManager());
                    


                    By default, the Application Server runs without a SecurityManager installed, so the above code should succeed.

                    • 7. Re: ClassNotFoundException while calling remote ejb3 across
                      Armin Vogt Newbie

                      The exception occurs right during the lookup. Not before.

                      I had a look at my exception. It states that the RMIClassLoader tries to loadProxy classes. It tries to load the interfaces that i dont have in my ear.

                      I had enabled the WebService (DownloadServerClasses=true).
                      I have a RMISecurityManager and a server.policy active with ALL priviliges for the server enabled.

                      Can i upload my slightly enhanced ScopedTest somewhere?
                      (I just added another @Remote interface 'SpecialTravelAgent
                      ' that is not known to the client and not used by the client but gets referenced by the StatelessRemoteProxy, so you might do it yourself)

                      And thank you very much so far for your attention

                      Regards,
                      Armin

                      • 8. Re: ClassNotFoundException while calling remote ejb3 across
                        Ron Sigal Master

                        Hi Armin,

                        Sorry I'm late getting back to you.

                        At this point we're getting beyond the scope of Remoting. I would suggest that you try the EJB 3.0 forum,

                        http://www.jboss.com/index.html?module=bb&op=viewforum&f=221

                        or the Installation, Configuration & DEPLOYMENT forum,

                        http://www.jboss.com/index.html?module=bb&op=viewforum&f=61.

                        If you post to another forum, maybe you could let us know where. I'd like to follow any further discussion.

                        Thanks,
                        Ron