Archived

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

Exception Handling

Hi,

We are using ICE v3.5.1

From a design perspective, we had one API (SubmitRequest) that the client used to communicate to the server. All the necessary parameters and relevant information regarding which object and method to invoke is packaged and serialized into byte array is passed. The server would return the output in the form of a byte array. This all worked very well.

This approach has some advantages:
1) We are not tightly coupled to SLICE to some extent
2) On the server side, we had one common exception handler.
3) Inputs and outputs serialized (protobuf)

Now we want to actually go with ICE all the way, meaning all the calls would be exposed via SLICE and would depend upon the ICE’s serializing and de-serializing techniques.

I have a put together a prototype (modified async example) with object adapter and 4 servants registered.

Servant registration:
adapter.add(new HelloI(_workQueue), communicator().stringToIdentity("hello"));
adapter.add(new CarI(), communicator().stringToIdentity("car"));
adapter.add(new PlaneI(), communicator().stringToIdentity("plane"));
adapter.add(new ShipI(), communicator().stringToIdentity("ship"));

Sever Config:
Hello.Endpoints=tcp -h localhost -p 10000

Client Config:
Hello.Proxy=hello:tcp -h localhost -p 10000
Car.Proxy=car:tcp -h localhost -p 10000
Plane.Proxy=plane:tcp -h localhost -p 10000
Ship.Proxy=ship:tcp -h localhost -p 10000


The calls from the client are going through to the server. No Issues.

I have few questions:
1) Is the approach in my sample correct to support multiple servants for a given object adapter?
2) If an operation is marked [amd] and is processed immediately on the server (meaning the request is not placed into the queue), is this equivalent to synchronous processing?
3) Is there a way to have one common handler for all the servants?
4) What benefits does this approach buy us (all-out SLICE) when compared to our first approach with one single call?

Regards,
Vishwa

Comments

  • benoit
    benoit Rennes, France
    Hi,
    vishreddyk wrote: »
    I have few questions:
    1) Is the approach in my sample correct to support multiple servants for a given object adapter?

    Yes, that's fine.
    2) If an operation is marked [amd] and is processed immediately on the server (meaning the request is not placed into the queue), is this equivalent to synchronous processing?

    Yes, if you send the response with the AMD callback object at the end of the implementation of your servant method, it's equivalent.
    3) Is there a way to have one common handler for all the servants?

    I suppose you mean a single implementation class to handle the implementation of multiple Slice interfaces? With the C# and Java mapping, you can generate TIE classes provided that you run the slice2cs or slice2java translator with the --tie command line option (or check the Tie check box in the Visual Studio Add-in).

    For example:
    // Slice (compiled with --tie)
    module Test {
        interface A {
           void op1();
        };
        interface B {
           void op2();
        };
    }
    
    // C#
    class ServantImpl : Test.AOperations_, Test.BOperations_
    {
        public override void op1(Ice.Current current)
        {
        }
        public override void op2(Ice.Current current)
        {
        }
    };
    
    ServantImpl impl = new ServantImpl();
    adapter.addWithUUID(new Test.ATie_(impl));
    adapter.addWithUUID(new Test.BTie_(impl));
    

    See Tie Classes in C-Sharp for more information.
    4) What benefits does this approach buy us (all-out SLICE) when compared to our first approach with one single call?

    You no longer have to perform the encoding/decoding of the requests with a 3rd party library and implement the dispatch logic on the server side.

    Depending on your needs, you might also find that the Slice language provides more features than what you're currently using. For instance, it supports exceptions, class inheritance, encoding of object graphs, slicing of unknown classes, etc. See The Slice Language chapter in the manual for more details on the slice language.

    Cheers,
    Benoit.
  • So when using Tie class approach, with what identity or name would the client gain access to the proxy.

    Currently I do:
    Communicator comm = communicator();
    return IAsyncRequestPrxHelper.checkedCast(comm.propertyToProxy("AsyncTest.Proxy"));

    On the server the servant is registered with name: "AsyncTest"

    Please advise.
  • benoit
    benoit Rennes, France
    A proxy is composed of the identity of the Ice object and the endpoint(s) of the Ice object adapter.

    So if you register the servant with the identity "plane" and if your object adapter listens on the endpoint "tcp -h localhost -p 12345", the proxy to invoke on the Ice object can be obtained by converting the string "plane:tcp -h localhost -p 12345" as shown here:
    // C#
    Ice.ObjectPrx prx = communicator.stringToProxy("plane:tcp -h localhost -p 12345").
    

    In your code, you create the proxy from a property (not from a string) with comm.propertyToProxy("AsyncTest.Proxy"). Your client sets this property either programmatically or reads it from a configuration file. The value of the property named AsyncTest.Proxy should be similar to the proxy string shown above.

    Whether or not you use the TIE approach to implement the servants is unrelated to identities or how proxies are created.

    In my example, I used the object adapter addWithUUID method to register the servants with unique identities but I could just as well have used the add method:
    adapter = comm.createObjectAdapterWithEndpoints("Adapter", "tcp -p 12345 -h localhost");
    ServantImpl impl = new ServantImpl();
    adapter.add(new Test.ATie_(impl), comm.stringToIdentity("car"));
    adapter.add(new Test.BTie_(impl), comm.stringToIdentity("plane"));
    

    In this example, a client could create the proxies from the strings "car:tcp -p 12345 -h localhost" and "plane:tcp -p 12345 -h localhost". You could also use properties and a configuration file to configure those proxies. This avoids hardcoding them in the code.

    For more information on proxies, object adapters, identities, properties, etc, I recommend to check the Ice Run Time in Detail chapter in the manual.

    Cheers,
    Benoit.