Archived

This forum has been archived. Please start a new discussion on GitHub.

ObjectAdapter.add - adding servants from an other processes scope

Hi.

My problem is that I want to register servants from several, distinct process scopes. But still the administration should be done by one defined ObjectAdapter. Thus, I'm trying to use Ice's RPC technique to make this ObjectAdapter accessible for clients which are not in the same process.
BUT ... when I try to add the ObjectAdapter like this:

/*Adding mObjectAdapter to make it available for clients outside this process' scope: */
myAdapter.add(mObjectAdapter, communicator().stringToIdentity("ServerAdapter") );

I get an error which says that the add(Object, Identity) method is not applicable for the argument ObjectAdapter (see the first argument).

Since I'm a newbie to Ice I would appreciate any hint how to fix this or how else my enterprise could be done.

Regards,
Patrick

p.s.:
Or in other words you could say I want to make an object instance available for RPC whereby the objects class (which therefore could be accounted as the servant) is already existing. So how can I create an Ice interface for an already existing object type (in this case Ice.ObjectAdapter)?

Comments

  • matthew
    matthew NL, Canada
    You would need to write an interface that you would then use to wrap the object adapter. We've done similar things actually in the Ice test suite... for an example, check out cpp/test/Ice/binding/Test.ice.
  • Thanks Matthew.

    I hoped for a given definition I could use but ok, I will write a small wrapper interface.

    Therefore I have one more question:

    In my small Ice definition I use one parameter which is of the type "Object". This type is not included in the basic slice types list. Also I can not find any Ice definition of that. Why is that? Is it a basic type and just not within the list?

    Regards and thanks for answering that fast.
    Patrick
  • By the way ... this is how my small Ice definition looks like:

    #include </usr/share/Ice-3.3.1/slice/Ice/Identity.ice>

    module Remote
    {

    interface RemoteObjectAdapter
    {
    /*
    * Add a servant to this object adapter's Active Servant Map.
    */
    void add(Object servant, Ice::Identity id);
    };

    };
  • matthew
    matthew NL, Canada
    Object is a built in type. That will pass the object by value across the wire. It means, however, that the object implementation must exist in the target namespace. Depending on your system this may or may not be difficult.

    I'm really not sure, however, what you are trying to accomplish with this architecture. What are your overall architectural goals?

    btw, doing
    #include </usr/share/Ice-3.3.1/slice/Ice/Identity.ice>
    

    Is not very portable. Its better to do:
    #include <Ice/Identity.ice>
    

    And then run the slice compiler with the -I path to your slice installation.
  • The overall goal is to have objects (the servants in Ice terminology) that will exist in several distinct processes. But since I don't want every of these processes to have his own server, I try to make one central point of registration. One ObjectAdapter with a single ASM. This must be accessible from other processes.
  • matthew
    matthew NL, Canada
    The overall goal is to have objects (the servants in Ice terminology) that will exist in several distinct processes. But since I don't want every of these processes to have his own server, I try to make one central point of registration.

    If you make objects remotely accessible then that process is, by definition, a server. Therefore I don't really understand your goal, or at least I don't understand how having a central object adapter reaches this particular goal. Another possible reason for my misunderstanding could be a terminology issue.

    If what you really want to do is control access to your resources then there are better and more convenient methods of doing so, such as Glacier2 (also a connection concentrator) and/or SSL.

    If this doesn't really reflect what you want, it would be best if you could illustrate your intended goal through example, or illustration.
  • Hi Matthew.

    Thank you for you patience. I try to explain my intent little more comprehensive.

    Imagine the following:

    There exists a process A. Process A holds an object which it wants to give remote access to. Therefore the object needs to be added to an ObjectAdapter's ASM. BUT I don't want the adapter to exist in the process A. Instead I want there to be a process (let's call it B). In this process B I want the adapter to exist.

    Now my problem is how to register the object in A at the adapter in process B?!

    To solve this I'm currently trying to give access to the adapter in process B via a proxy to this adapter. This roughly looks like this:
    /* Obtain an object proxie to the adapter running in process B */
    Ice.ObjectPrx objPrx = mCommunicator.stringToProxy("RemoteObjectAdapter:tcp -h 127.0.0.1 -p 10000"); 
    
    /* Now cast it to the type RemoteObjectAdapterPrx */
    Remote.RemoteObjectAdapterPrx mRemoteAdapter = Remote.RemoteObjectAdapterPrxHelper.uncheckedCast(objPrx); 
    
    /* Finally process A adds his servant object to process B's adapter ASM */
    mRemoteAdapter.add( new HelloI(), mCommunicator.stringToIdentity("HelloObject") );
    

    My problem right now is, that the last call to the add method results in a NullPointerException and I don't know why.

    If you ask for the reason, this is simply because of I will have a plenty of processes like A, which serve with objects. If I don't have a central ObjectAdapter I will end up with a plenty of adapters bound to a plenty of ports listening at.

    I hope this is more comprehensive than my explenations before.
    Regards,
    Patrick
  • benoit
    benoit Rennes, France
    Hi,

    Could you post the stack trace of the NullPointerException exception? It's not clear to me why this fails but seeing the stack trace of the exception should give us some clues.

    Cheers,
    Benoit.
  • matthew
    matthew NL, Canada
    kenpark wrote: »
    There exists a process A. Process A holds an object which it wants to give remote access to. Therefore the object needs to be added to an ObjectAdapter's ASM. BUT I don't want the adapter to exist in the process A. Instead I want there to be a process (let's call it B). In this process B I want the adapter to exist.

    If you want the object to live in B, then you can pass the object by value over the wire. However, this means that B needs an implementation of each of these objects, which is frequently not desirable. It also means that your system is not very distributed, and you cannot take advantage of the additional resources of other hosts, which also may not be desirable.

    If you do not pass the object by value, but rather by proxy, then you are not having the effect you assume. Basically, you'll still host the objects in A, and provide access through B. B in effect will be a connection concentrator, in a very inefficient way. In addition A will still also be a server, which isn't what you want.
    If you ask for the reason, this is simply because of I will have a plenty of processes like A, which serve with objects. If I don't have a central ObjectAdapter I will end up with a plenty of adapters bound to a plenty of ports listening at.
    ...

    You still don't really explain why that is a problem for you. Why are listening ports an issue for you, and why are multiple processes an issue? Most people use Ice because they want to create distributed systems, not create centralized systems as you appear to want to do.

    I really recommend describing your problem from a higher level describing what you want to achieve not how you want to achieve it. I say this because stating how you want to achieve your goal locks out other, potentially better solutions.
  • Here goes the stack trace:
    W/System.err(  690): 6/30/09 11:55:56:644 error: Ice Acceptor Thread: 127.0.0.1:10000: acceptAsync:                                                                         
    W/System.err(  690): 127.0.0.1:10000                                                                                                                                        
    W/System.err(  690): java.lang.NullPointerException                                                                                                                         
    W/System.err(  690):    at IceInternal.Network.addressesToString(Network.java:1139)                                                                                         
    W/System.err(  690):    at IceInternal.Network.fdToString(Network.java:1115)                                                                                                
    W/System.err(  690):    at IceInternal.TcpTransceiver.<init>(TcpTransceiver.java:345)                                                                                       
    W/System.err(  690):    at IceInternal.TcpAcceptor.accept(TcpAcceptor.java:52)                                                                                              
    W/System.err(  690):    at IceInternal.IncomingConnectionFactory.acceptAsync(IncomingConnectionFactory.java:473)                                                            
    W/System.err(  690):    at IceInternal.IncomingConnectionFactory.access$000(IncomingConnectionFactory.java:14)                                                              
    W/System.err(  690):    at IceInternal.IncomingConnectionFactory$1.run(IncomingConnectionFactory.java:328)                                                                  
    W/System.err(  690):    at java.lang.Thread.run(Thread.java:1058)  
    

    Your objections seem justifiable. I will verify my concept and take your hints in account.

    Thanks, at least it is an alternative I will have some try on.
    Cheers,
    Patrick
  • Matthew,

    are there any sources for the IceAndroid runtime available? This would help me in debugging the exception.
  • benoit
    benoit Rennes, France
    Hi,

    The source code should already be included with the Ice for Android distribution that you downloaded (see the INSTALL file for instructions on how to build the source code).

    I believe one of my colleague ran into this issue as well, he will follow up on the best way to fix it. For now, you could simply comment out the line 1139 in java/src/IceInternal/Network.java.

    Cheers,
    Benoit.
  • matthew
    matthew NL, Canada
    Both the sources for android and Ice are available. I built an Android source jar archive when I was working on Ice for Android, and it was a help.

    However, there is no need for you to look into the problem. We've duplicated your reported issue and will provide a patch in the near future.
  • mes
    mes California
    Unfortunately, the networking APIs in Android are still incomplete. We have filed several bugs but they are slow in getting fixed.

    To work around this issue, you can comment out the offending line as Benoit suggested above, or you can make the code a bit more forgiving as follows:
    // java/src/IceInternal/Network.java, line 1137
    StringBuffer s = new StringBuffer();
    s.append("local address = ");
    if(localAddr != null)
    {
        s.append(localAddr.getHostAddress());
    }
    else
    {
        s.append("<not available>");
    }
    s.append(':');
    ...
    
    You will need to rebuild IceAndroid.jar by running ant in the IceAndroid-0.1.0/java subdirectory. Afterward, you should replace IceAndroid.jar in your Ice installation directory with the updated version you just compiled.

    Regards,
    Mark
    kenpark wrote: »
    Here goes the stack trace:
    W/System.err(  690): 6/30/09 11:55:56:644 error: Ice Acceptor Thread: 127.0.0.1:10000: acceptAsync:                                                                         
    W/System.err(  690): 127.0.0.1:10000                                                                                                                                        
    W/System.err(  690): java.lang.NullPointerException                                                                                                                         
    W/System.err(  690):    at IceInternal.Network.addressesToString(Network.java:1139)                                                                                         
    W/System.err(  690):    at IceInternal.Network.fdToString(Network.java:1115)                                                                                                
    W/System.err(  690):    at IceInternal.TcpTransceiver.<init>(TcpTransceiver.java:345)                                                                                       
    W/System.err(  690):    at IceInternal.TcpAcceptor.accept(TcpAcceptor.java:52)                                                                                              
    W/System.err(  690):    at IceInternal.IncomingConnectionFactory.acceptAsync(IncomingConnectionFactory.java:473)                                                            
    W/System.err(  690):    at IceInternal.IncomingConnectionFactory.access$000(IncomingConnectionFactory.java:14)                                                              
    W/System.err(  690):    at IceInternal.IncomingConnectionFactory$1.run(IncomingConnectionFactory.java:328)                                                                  
    W/System.err(  690):    at java.lang.Thread.run(Thread.java:1058)  
    
  • Thank you guys for the support.

    I will try to fix my problems according to your suggestions concerning IceAndroid.jar. Besides I will evaluate an alternative approch keeping Matthew's questions/hints in mind.

    I will get back to this thread and post my results.

    Regards,
    Patrick