Archived

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

Problem with "addWithUUID", while implementing the facets

Hi all,

1). I am facing a problem in adding a servant object to ObjectAdapterPtr using addWithUUID. The servant object is not getting added to the adapter, so client is "Aborting" when it triews to down cast to PrinterPrx using "checkedCast". The following code snippet is in my client.cpp file

Ice::ObjectPrx base = ic->stringToProxy("SimplePrinter:tcp -h 192.168.147.202 -p 10000");
PrinterPrx printer = PrinterPrx::checkedCast(base);

2). If I am using ObjectAdapterPtr's "add()" method instead of "addWithUUID() ". The servant object is getting added successfully and "client" is able to connect to the server without any changes in the code. With the following code snippet I tried to add my servant object to the ObjectAdapterPtr.

Ice::ObjectAdapterPtr adapter
= ic->createObjectAdapterWithEndpoints(
"SimplePrinterAdapter","tcp -h 192.168.147.202 -p 10000");
PrinterPtr printer = new PrinterI();
// adapter->add(printer,Ice::stringToIdentity("SimplePrinter" ));
Ice::ObjectPrx printprx = adapter->addWithUUID(printer);

Here I have commented the line which uses "add()" method. If I release that line then it is getting added and client is also working fine.

3). The following exception is caught when I try to run the client, when the server is using "addWithUUID()".

[root@mailserver facets]# ./client
Outgoing.cpp:359: Ice::ObjectNotExistException:
object does not exist
identity: SimplePrinter
facet:
operation: ice_isA

4). In the Ice manual document, in the "32 .Facets and Versioning " chapter it is mentioned that, if we want to add any additional facet, then we have to use addWithUUID to get the "Identity" of default facet. And we need to use this "Identity" when we are adding additional facets. But I am facing problem while using "addWithUUID()" to add servant object.

Is it the only way to implement facet functionality?

Please help me how to resolve this issue. I am attaching the files I am using in my application. Can any one provide me with any example which implements facets.

Comments

  • matthew
    matthew NL, Canada
    Please don't post the same question twice. Once will get our attention :)

    The string SimplePrinter:tcp -h 192.168.147.202 -p 10000 is decomposed into two elements. The first is the identity of the object you want to contact. The second is the endpoints (and endpoint properties) wher e the object is located.

    In this case the identity you have selected is "SimplePrinter".

    When you add the object to the object adapter you tell the object adapter the identity that this object will use. When you use add with the identity "SimplePrinter" it works since that is the identity you have provided in the proxy. However, when you use addWithUUID a unique identity is generated by the OA (the identity is in the form of a UUID which is something like "A210254E-0E89-4F07-A939-EAC40C26FE1F"

    Generally UUIDs are used for objects that your server generates if you use something like a factory pattern. You typically will have at least one object that is accessible through some well known identity -- such as SimplePrinter.

    It seems that you have some fundamental misunderstandings about the Ice object model. I recommend that you fully understand this before starting to look at facets. What exactly do you want to use facets for?
  • Problem in creating the proxy

    Hi all,

    I am trying to implement two facets in server, and I am trying to access both facets from client. I have succeded in invoking the method of 1st facet, when I tried to access the method of 2nd facet I am facing problem's. I am getting the exception "/usr/include/IceUtil/Handle.h:39: IceUtil::NullHandleException".
    The following are the details of my application.

    1). In server I have implemented two servants for two interfaces. These interfaces are in two different modules. I have created the objects and registered them in the server.cpp. I am adding the servant objects to adapter in the following way:

    Ice::ObjectAdapterPtr adapter
    = ic->createObjectAdapterWithEndpoints(
    "SimplePrinterAdapter","tcp -h 192.168.147.202 -p 10000");
    Ice::ObjectPtr object = new PrinterI;
    PrinterPtr printer = new PrinterI;
    DisplayPtr display = new DisplayI;
    adapter->add(object,Ice::stringToIdentity("SimplePrinter"));
    Ice::ObjectPrx printprx = adapter->addWithUUID(printer);
    adapter->addFacet(display,printprx->ice_getIdentity(),"Display");

    2). In client I am trying to get the proxies for the two servants in the following way:

    Ice::ObjectPrx base = ic->stringToProxy("SimplePrinter:tcp -h 192.168.147.202 -p 10000");
    PrinterPrx printer = PrinterPrx::checkedCast(base);
    if (!printer)
    throw "Invalid proxy";
    printer->printstring("FROM CLIENT",s2);
    cout<<s2<<endl;
    DisplayPrx disp = DisplayPrx::checkedCast(printer,"Display");
    if (!disp)
    {
    disp->Disp("FROM CIENT 2nd FACET");
    }

    In this example I am able to got the "PrinterPrx" which I made as a default facet. I added "display" as the 2nd facet, but when I tried to call Disp() function of "display", I am getting the following exception: "/usr/include/IceUtil/Handle.h:39: IceUtil::NullHandleException".

    Please help me how to get the 2nd facet proxy and hence call the method in the 2nd facet after I add this facet with UUID in server.
  • matthew
    matthew NL, Canada
    Your code is wrong. In the client you are getting the facet from the object with the identity "SimplePrinter". However in your code you add it to whatever object has the generated UUID. Furthermore, your logic is incorrectly reversed in the client; hence the NullHandleException.

    It should read something like:
    Ice::ObjectAdapterPtr adapter
    = ic->createObjectAdapterWithEndpoints(
    "SimplePrinterAdapter","tcp -h 192.168.147.202 -p 10000");
    Ice::ObjectPtr object = new PrinterI;
    PrinterPtr printer = new PrinterI;
    DisplayPtr display = new DisplayI;
    Ice::Identity id = Ice::stringToIdentity("SimplePrinter")
    adapter->add(object, id);
    adapter->addFacet(display, id,"Display");
    

    and then later
    DisplayPrx disp = DisplayPrx::checkedCast(printer,"Display");
    if (disp)
    {
       disp->Disp("FROM CIENT 2nd FACET");
    }
    

    I don't know what you have in mind to do with facets, but looking at this code I suspect what you are trying to do would be an abuse of the object model.
  • facets

    Thank you Mathew,

    Now the program is running fine!

    Actually we have a server which exposes two functions. Now we have to add two more functions to it. After making this change we have to support old clients and new clients. So to support both version of clients I am implementing the facets.

    In the Ice document "32.Facets and Versions" chapter, it is specifying that we need to place the new functions in a separate module and interfaces. Then we have to provide separate servant for that.

    Then we have to add the 1st servant object as a defualt facet, and we have to use the id,which we got while adding the first facet. Using that id we need to add the 2nd object as another facet.

    With your help I am getting the id of the "SimplePrinter" and I am using the same id, to add the 2nd facet. Is it the right way?

    Please advice
  • matthew
    matthew NL, Canada
    Yes, that sounds correct.

    Note that depending on exactly what you are doing you may not need to use facets to version.If you do not change any of your existing datatypes or methods and instead only add new datatypes and methods to existing interfaces AND you upgrade all servers you don't need to version at all like this (this depends on your deployment -- perhaps you can update all servers, perhaps you cannot. if you cannot, you must version with some other mechanism like facets).

    Old clients won't use the new interfaces and since the old interfaces are the same then everything will continue to work. New clients will use the new methods and also will work correctly.

    You really only need to version like this if you cannot upgrade all of the servers and want old & new clients to work with the servers, or if you actually change datatypes or the signatures of interface methods.
  • Just to add to this... As Matthew says, if you can upgrade all the servers in the system to the new version, you get away with simply adding an operation to an interface. On the other hand, if you need to have old- and new-version servers co-exist in the system, adding an operation to an interface is a no-no. In that case however, instead of using facets, I'd consider versioning by derivation:
    interface Old
    {
        void op();
    };
    
    interface New extends Old
    {
        void extraOp();
    };
    
    That allows old and new servers to co-exist cleanly, and also allows old and new clients to co-exist cleanly. For example, suppose that you have an operation in the original system like this:
    interface Foo
    {
        Old get();
    };
    
    Old servers return an instance of type Old from get(), and new servers return an instance of type New from get. This works, because New is derived from Old.

    Old clients are no wiser: they think of the returned proxy as being of type Old; whether the actual run-type of the proxy is Old or New doesn't matter to these clients.

    New clients, who know about New can call get() and then attempt a checkedCast to New. If that works, they are dealing with a new server and can call extraOp() on the down-cast proxy; if the cast fails, they are dealing with an older server and can only call op().

    Cheers,

    Michi.