Announcement Announcement Module
Collapse
No announcement yet.
A sever side object that hands back "remoted" refe Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • A sever side object that hands back "remoted" refe

    Hi,

    I'm having my clients connect a server side factory that hands back refs to remoted objects that also live in the server...

    Lets say I am trying to return an object that implements the IFoo interface ( and the server side object that implements it is Foo )...

    So, the server side config file has something like:
    ----------------------------------------------
    <bean id="myFooObject" class="Foo" />

    <bean id="myRemotedFoo" class="org.springframework.remoting.rmi.RmiService Exporter">
    <property name="service"><ref local="myFooObject"/></property>
    <property name="serviceInterface">
    <value>IFoo</value>
    </property>
    <property name="serviceName"><value>someServiceName</value></property>
    <property name="registryPort"><value>1099</value></property>
    </bean>

    ---------------------------------

    Now I want my "factory" object to hand back a ref to my remoted foo...

    This does not work ( class cast exception when trying to cast to interface type), but this is how I would assume you would do it:

    ------------------------------
    class MyFactory
    {
    ...
    public IServerServiceFactory getLocalServiceFactory() {
    // context is a FileSystemXmlApplicationContext

    Object o = context.getBean("myRemotedFoo");
    System.out.println(o);
    //note that o is an instance of
    //org.springframework.remoting.rmi.RmiServiceExporte r
    IFoo sf = (IServerServiceFactory)o;
    }
    }

    -----------------------

    Do I need to lookup the object in RMI on the serverside ( as if I were a client ), ( e.g. use a RmiProxyFactoryBean ) ? So then I'd have client and server config for objects living in the same server?

    Thanks in advance!!

  • #2
    Putting a RmiProxyFactoryBean in the server side spring config did not work ( I'm assuming that the service has not been created yet? )

    For example, I used:

    <bean id="myFooObjectStub" class="org.springframework.remoting.rmi.RmiProxyFa ctoryBean">
    <property name="serviceInterface">
    <value>IFoo</value>
    </property>
    <property name="serviceUrl">
    <value>rmi://localhsot:1099/someServiceName</value>
    </property>
    </bean>

    --------------

    I get the following exception when trying to create my ApplicationContext:

    org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'myFooObjectStub' defined in file path [c:\stuff.xml]: Initialization method of bean failed; nested exception is java.rmi.NotBoundException: someServiceName

    ----------------

    But the RmiProxyFactoryBean appears AFTER the RmiServiceExporter in the spring config file...so I don't know what is going on...

    Comment


    • #3
      and...when I try to "manually" create and use a RmiProxyFactoryBean server side ( that i would hand back from my factory), and then invoke server side ( or client side ) using this code:
      ----------------------------

      RmiProxyFactoryBean factory = new RmiProxyFactoryBean();
      factory.setServiceInterface( IFoo.class);
      String url = "rmi://localhost:1099/someServiceName";
      factory.setServiceUrl(url);
      factory.afterPropertiesSet();
      IFoo foo = (IFoo)factory.getObject();

      foo.doSomethingUserfull();
      (kaboom!)

      ---------------------
      i get the following on the call "doSomethingUserfull"

      org.springframework.remoting.RemoteAccessException : Cannot access RMI invoker for [rmi://localhost:1099/someServiceName]; nested exception is java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
      java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.springframework.aop.framework.JdkDynamicAopPro xy
      java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
      java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.springframework.aop.framework.JdkDynamicAopPro xy
      at sun.rmi.server.UnicastRef.invoke(Unknown Source)
      ..
      /..

      Comment


      • #4
        I get the following exception when trying to create my ApplicationContext:

        org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'myFooObjectStub' defined in file path [c:\stuff.xml]: Initialization method of bean failed; nested exception is java.rmi.NotBoundException: someServiceName

        ----------------

        But the RmiProxyFactoryBean appears AFTER the RmiServiceExporter in the spring config file...so I don't know what is going on...
        Try setting the depends-on property of your RmiProxyFactoryBean, so that it depends on the service exporter. Beans are not instantiated in the order that they appear in the config file.

        Comment


        • #5
          Thanks for the "depends-on" tip. that fixed my start-up dependancy but I still have my original problem, i cannot return a "remoted" object...

          The exception i get on the client side by calling "getFoo" on my factory is (someServiceName is my factory):

          ----------------------------

          org.springframework.remoting.RemoteAccessException : Cannot access RMI invoker for [rmi://localhost:1099/someServiceName]; nested exception is java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
          java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.springframework.aop.framework.JdkDynamicAopPro xy
          java.rmi.UnmarshalException: error unmarshalling return; nested exception is:
          java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.springframework.aop.framework.JdkDynamicAopPro xy
          at sun.rmi.server.UnicastRef.invoke(Unknown Source)
          at org.springframework.remoting.rmi.RemoteInvocationW rapper_Stub.invokeRemote(Unknown Source)
          at org.springframework.remoting.rmi.RmiClientIntercep tor.invoke(RmiClientInterceptor.java:73)
          at org.springframework.aop.framework.ReflectiveMethod Invocation.proceed(ReflectiveMethodInvocation.java :196)
          at org.springframework.aop.framework.JdkDynamicAopPro xy.invoke(JdkDynamicAopProxy.java:135)
          at $Proxy0.getLocalServiceFactory(Unknown Source)
          at foo.ServiceFactoryTest.testClientSide(ServiceFacto ryTest.java:79)
          at foo.ServiceFactoryTest.main(ServiceFactoryTest.jav a:53)
          Caused by: java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: org.springframework.aop.framework.JdkDynamicAopPro xy
          at java.io.ObjectInputStream.readObject0(Unknown Source)
          at java.io.ObjectInputStream.defaultReadFields(Unknow n Source)
          at java.io.ObjectInputStream.readSerialData(Unknown Source)
          at java.io.ObjectInputStream.readOrdinaryObject(Unkno wn Source)
          at java.io.ObjectInputStream.readObject0(Unknown Source)
          at java.io.ObjectInputStream.readObject(Unknown Source)
          at sun.rmi.server.UnicastRef.unmarshalValue(Unknown Source)
          ... 8 more
          Caused by: java.io.NotSerializableException: org.springframework.aop.framework.JdkDynamicAopPro xy
          at java.io.ObjectOutputStream.writeObject0(Unknown Source)
          at java.io.ObjectOutputStream.defaultWriteFields(Unkn own Source)
          at java.io.ObjectOutputStream.writeSerialData(Unknown Source)
          at java.io.ObjectOutputStream.writeOrdinaryObject(Unk nown Source)
          at java.io.ObjectOutputStream.writeObject0(Unknown Source)
          at java.io.ObjectOutputStream.writeObject(Unknown Source)
          at sun.rmi.server.UnicastRef.marshalValue(Unknown Source)
          at sun.rmi.server.UnicastServerRef.dispatch(Unknown Source)
          at sun.rmi.transport.Transport$1.run(Unknown Source)
          at java.security.AccessController.doPrivileged(Native Method)
          at sun.rmi.transport.Transport.serviceCall(Unknown Source)
          at sun.rmi.transport.tcp.TCPTransport.handleMessages( Unknown Source)
          at sun.rmi.transport.tcp.TCPTransport$ConnectionHandl er.run(Unknown Source)
          at java.lang.Thread.run(Unknown Source)

          Comment


          • #6
            I'm not sure that it would be safe to return a remote reference to a client...

            Lets say I have a service (Foo) on my network and you call into that from your network. From your point of view you may seem my service at rmi://james.domain:1099/... However, that would most likely be routed to some internal host (e.g. - 172.18.123.123 on port 4444).

            That's all fine and good since the network components will take care of the address translation and getting the packets to where they need to go.

            However...

            If my Foo service tries to return a remote reference to you for my Bar service, there's a good chance it'll use the internal address (e.g. - 172.18.234.234 on port 5555) or internal hostname (e.g. - servicehost.james.domain on port 5555) for the service. The client proxy created with that address would be such that there's no way your client will be able to use it to access the service. Specifically, the network routers between the client and server wouldn't know how to get the packets from the client to the server.

            What might work would be to send your client the externally resolvable serviceURL. That would be far different than providing the already-resolved client proxy instance.

            Comment


            • #7
              Thanks for your reply jcej.

              Unfortunately I'm not in a position where I can dictate architecture on the project I'm on.

              To summarize my question:
              ==================

              Is it possible to return a remoted object from another remoted interface?

              Comment


              • #8
                Okay, let me see if I understand this correctly...

                You have a client that is connecting to a remote factory by a local rmi proxy. That factory returns beans to the client to operate on. But the catch is... the beans that it returns are also remote proxies. And the problem you are getting is that you cannot transport the remoted beans across the wire, because the dynamic proxy used is not serializable. And even if you could, the resolved references might be broken.

                I might be missing something but I can't see that his will work in its present form. Could your factory generate a new remote service wrapper for a requested bean and automatically provide that to the client instead? You'd be adding another layer of indirection - the client will get a remote proxy that calls a remote service on the server, that in turn calls a remote proxy to the *actual* remote service you want.

                Comment


                • #9
                  Originally posted by dhewitt
                  Okay, let me see if I understand this correctly...

                  You have a client that is connecting to a remote factory by a local rmi proxy. That factory returns beans to the client to operate on. But the catch is... the beans that it returns are also remote proxies. And the problem you are getting is that you cannot transport the remoted beans across the wire, because the dynamic proxy used is not serializable. And even if you could, the resolved references might be broken.

                  I might be missing something but I can't see that his will work in its present form. Could your factory generate a new remote service wrapper for a requested bean and automatically provide that to the client instead? You'd be adding another layer of indirection - the client will get a remote proxy that calls a remote service on the server, that in turn calls a remote proxy to the *actual* remote service you want.
                  Wow, thanks for the reply dhewitt...

                  Well, I'm a complete noob to spring, but this sounds like pretty much what i want to do...

                  I'm afraid I don't know what a "new remote service wrapper" is though...you mean another RmiServiceExporter for the IFoo instance to go around my original RmiServiceExporter? I'm not sure what that gets me...? And i would pass back the outer most RmiServiceExporter? ?

                  If you mean : have a sever side RmiProxyFactoryBean for my server side RmiServiceExporter and hand back what I get from the ApplicationContext for the RmiProxyFactoryBean ... I tried that and it blew up on the client side ( see abouve )...

                  Thanks again for the reply!!

                  Comment


                  • #10
                    Well, its basically what jcej suggested - you would essentially have to pass back the externally resolvable serviceURL. What you could do though to make the whole process transparant to the client is this (and I'm speaking hypothetically here, I have absolutely no idea if this will work or fits your architecture!).

                    I'll refer to the following contexts:
                    Local (meaning client)
                    Server (meaning where your remote factory bean resides)
                    Remote (meaning where your eventual remote service resides)

                    You would need to make two modifications:
                    - Change your factory so that, rather than returning a remote proxy, it creates an RmiServiceExporter for the proxy in the server's context and returns the servicename and service interface class to the local caller
                    - Create a new factory in the local context that delegates to the server factory, takes the returned servicename and interface, and creates a new RmiProxyFactoryBean that exposes the server rmi service to the local client.

                    Then your client would call the local factory, the factory would call the proxy to the factory on the server and get the details of the rmi service in response. The local factory would then wrap those up in a proxy in the local context and return *that* to the client. Phew. If that works you could start worrying about caching references and avoiding double lookups.

                    Does this make any kind of sense?

                    Comment


                    • #11
                      thanks for the post dhewitt.

                      i think i get it... i guess the down side is the the it would not be a traditional "factory" interface...e.g.

                      interface IFactory
                      {
                      IFoo getFoo();
                      IBar getBar();
                      }

                      -------

                      insead it would be something like:

                      interface IFactory
                      {
                      ServiceInfo getFoo();
                      ServiceInfo getBar();
                      }

                      Where ServiceInfo is passed by value and contains servicename and service interface class.

                      The rest is pretty clear...
                      ------------

                      Comment

                      Working...
                      X