Announcement Announcement Module
Collapse
No announcement yet.
Using RMI on the Spring Application Platform Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Using RMI on the Spring Application Platform

    Hello

    I'm having some problems using Spring RMI services in combination with the Spring Application Platform.
    Well I can publish the service and access it from my Eclipse RCP client (using Spring DM), I can transfer simple Strings but as soon as I try to get or send an Object I get the following exceptions on my client:

    When sending:
    org.springframework.remoting.RemoteAccessException : Could not access remote service [rmi://localhost:1195/TestService]; nested exception is java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
    java.lang.ClassNotFoundException: com.blogspot.swissdev.servicetest.TestObject in PlatformBundleClassLoader: [bundle=org.springframework.context_2.5.5.BUILD-20080530] (no security manager: RMI class loader disabled)
    at org.springframework.remoting.rmi.RmiClientIntercep torUtils.convertRmiAccessException(RmiClientInterc eptorUtils.java:181)
    at org.springframework.remoting.rmi.RmiClientIntercep tor.doInvoke(RmiClientInterceptor.java:342)
    at org.springframework.remoting.rmi.RmiClientIntercep tor.invoke(RmiClientInterceptor.java:258)
    at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :171)
    at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:204)
    at $Proxy2.setObject(Unknown Source)
    .........

    When receiving:
    org.springframework.remoting.RemoteAccessException : Could not access remote service [rmi://localhost:1195/TestService]; nested exception is java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
    java.lang.ClassNotFoundException: com.blogspot.swissdev.servicetest.TestObject (no security manager: RMI class loader disabled)
    at org.springframework.remoting.rmi.RmiClientIntercep torUtils.convertRmiAccessException(RmiClientInterc eptorUtils.java:181)
    at org.springframework.remoting.rmi.RmiClientIntercep tor.doInvoke(RmiClientInterceptor.java:342)
    at org.springframework.remoting.rmi.RmiClientIntercep tor.invoke(RmiClientInterceptor.java:258)
    ...........


    On the server I have one simple Bundle Project, importing the library org.springframework.spring and exporting the package with the business object in it.

    My RCP client is one simple RCP example plug-in (the one with a view), including the Spring DM plug-ins in the launch.
    Spring DM is launched and I access the service when double clicking on a item in the view, so everything is loaded.


    Here my access to the service:

    ITestService service = Activator.getDefault().getService(ITestService.cla ss.getName());
    System.out.println(service.getTestString());
    service.setObject(new TestObject());
    service.getObject();


    Here the getService method:

    public <T> T getService(String serviceClassName) {
    ServiceReference reference = context.getServiceReference(serviceClassName);
    if ( reference != null ) {
    Object service = context.getService(reference);
    if ( service != null )
    return (T) service;
    }
    throw new RuntimeException("Service not found in the registry.");
    }


    The print of getTestString works and the other calls fail.
    Did anybody have the same exception or any clue why org.springframework.context doesn't see my object?

    Thanks for any help!!!

  • #2
    Using RMI on the Spring Application Platform

    For me it seems that your client doesn't know your DTO.
    You have to externalize your DTOs to a client-server project and include it on both sides

    Comment


    • #3
      Using RMI on the Spring Application Platform

      It's not caused by the DTO's not being present. I just tried a small remoting example and it failed, indeed. The key is this part:
      java.lang.ClassNotFoundException: com.blogspot.swissdev.servicetest.TestObject in PlatformBundleClassLoader: [bundle=org.springframework.context_2.5.5.BUILD-20080530]

      You can see that this comes from the classloader of the spring context bundle, which cannot access the TestObject class.

      In my case, there's a bit more in the stacktrace sent to the client that seems to further explain the issue:
      Caused by: java.lang.ClassNotFoundException: example.domain.MyDomainClass in PlatformBundleClassLoader: [bundle=org.springframework.context_2.5.5.A] (no security manager: RMI class loader disabled)
      at sun.rmi.server.LoaderHandler.loadClass(LoaderHandl er.java:375)
      at sun.rmi.server.LoaderHandler.loadClass(LoaderHandl er.java:165)
      at java.rmi.server.RMIClassLoader$2.loadClass(RMIClas sLoader.java:620)
      at java.rmi.server.RMIClassLoader.loadClass(RMIClassL oader.java:247)
      at sun.rmi.server.MarshalInputStream.resolveClass(Mar shalInputStream.java:197)
      at java.io.ObjectInputStream.readNonProxyDesc(ObjectI nputStream.java:1575)
      at java.io.ObjectInputStream.readClassDesc(ObjectInpu tStream.java:1496)
      at java.io.ObjectInputStream.readOrdinaryObject(Objec tInputStream.java:1732)
      at java.io.ObjectInputStream.readObject0(ObjectInputS tream.java:1329)
      at java.io.ObjectInputStream.readArray(ObjectInputStr eam.java:1667)
      at java.io.ObjectInputStream.readObject0(ObjectInputS tream.java:1323)
      at java.io.ObjectInputStream.defaultReadFields(Object InputStream.java:1945)
      at java.io.ObjectInputStream.readSerialData(ObjectInp utStream.java:1869)
      at java.io.ObjectInputStream.readOrdinaryObject(Objec tInputStream.java:1753)
      at java.io.ObjectInputStream.readObject0(ObjectInputS tream.java:1329)
      at java.io.ObjectInputStream.readObject(ObjectInputSt ream.java:351)
      at sun.rmi.server.UnicastRef.unmarshalValue(UnicastRe f.java:306)
      at sun.rmi.server.UnicastServerRef.dispatch(UnicastSe rverRef.java:290)
      ... 9 more
      Caused by: java.lang.ClassNotFoundException: example.domain.MyDomainClass
      at org.eclipse.osgi.framework.internal.core.BundleLoa der.findClassInternal(BundleLoader.java:481)
      at org.eclipse.osgi.framework.internal.core.BundleLoa der.findClass(BundleLoader.java:397)
      at org.eclipse.osgi.framework.internal.core.BundleLoa der.findClass(BundleLoader.java:385)
      at org.eclipse.osgi.internal.baseadaptor.DefaultClass Loader.loadClass(DefaultClassLoader.java:87)
      at com.springsource.platform.osgi.framework.equinox.P latformBundleClassLoader.loadClass(PlatformBundleC lassLoader.java:134)
      at java.lang.ClassLoader.loadClass(ClassLoader.java:2 51)
      at java.lang.ClassLoader.loadClassInternal(ClassLoade r.java:319)
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:247)
      at sun.rmi.server.LoaderHandler.loadClass(LoaderHandl er.java:359)
      ... 26 more


      It looks the LoaderHandler from the RMI Registry uses the classloader that belongs to the Spring bundle, which cannot see the domain classes so they can't be unmarshalled. Creating a new RMI Registry from within the server bundle doesn't make a difference.
      I must admit that I don't know how using an RMI Registry that can see your classes so they can be unmarshalled should be done in an OSGi environment.
      Maybe someone with more OSGi experience can enlighten us?

      BTW, interestingly enough this stacktrace doesn't seem to be logged on the server, but only gets sent to the client. Is the FFDC support not able to capture exceptions thrown by the RMI server?

      Joris

      Comment


      • #4
        Using RMI on the Spring Application Platform

        A bit of googling seems to indicate that this is not a trivial problem:
        http://www.eclipsecon.org/2007/index.php?page=sub/&id=3987
        although I didn't even try to let my class be loaded dynamically, I simply included it on the client and in a server bundle.
        To make my scenario work, the RMI Registry should be smart enough to know what classloader to use for unmarshalling based on the registered service, or something like that. Probably not something you can do with vanilla OSGi, since there is no import of the parameter classes and thus no class space that will work. But I haven't read the OSGi specs yet and really don't know enough about this stuff...
        Maybe there's an Equinox-specific hook that could be used here?

        Comment


        • #5
          Using RMI on the Spring Application Platform

          This is known issue with OSGi and RMI. I've created a JIRA to track this (https://issuetracker.springsource.com/browse/PLATFORM-129) - we'll take a look at what we can do in the Platform to make this easier.

          Rob

          Comment


          • #6
            Using RMI on the Spring Application Platform

            Thanks for the information everyone, great help!!!
            robharrop: thanks for tracking, when do you think you will get to it? which version?

            Comment


            • #7
              Using RMI on the Spring Application Platform

              Flavio,

              We won't get to this for version 1 - we have frozen the feature set now are we're just fixing bugs. It will certainly be on our roadmap for the next release - I'll be announcing dates for the roadmap over the next few weeks.

              Regards,

              Rob

              Comment


              • #8
                Using RMI on the Spring Application Platform

                ok, thanks.

                Do you think there will be problems using spring web services instead of RMI? Is this the same issue or does the platform handle it different?

                Comment


                • #9
                  Using RMI on the Spring Application Platform

                  Flavio,

                  There should be no problem with using Spring Web Services. RMI usage has some class loading issues when used in conjunction with OSGi. These issues are not present in Spring Web Services.

                  Rob

                  Comment


                  • #10
                    Using RMI on the Spring Application Platform

                    Hello,
                    Just to mention that I was able of successfully using Hessian remoting with S2AP, where I use Hessian + Spring's Dispatcher Servlet in the server side to export services, and retrieve them using Spring DM + Hessian on the client-side (an Eclipse RCP application).

                    So you might consider using Hessian instead of RMI ?

                    Cheers,
                    Jawher.

                    Comment


                    • #11
                      Using RMI on the Spring Application Platform

                      Thanks for the tip Jawher!!! I'll do that

                      Comment


                      • #12
                        Using RMI on the Spring Application Platform

                        How did you implement Hessian on your RCP Client? Since Spring DM doesn't include the org.springframework.remoting.caucho package.
                        Did you make a separated plug-in including the package and dependencies?

                        Comment


                        • #13
                          Using RMI on the Spring Application Platform

                          Nevermind, found it in the spring-web jar!

                          Comment

                          Working...
                          X