The ServantLocator Interface
A servant locator has the following interface:
module Ice {
local interface ServantLocator {
["UserException"]
Object locate(Current curr, out LocalObject cookie);
["UserException"]
void finished(Current curr, Object servant, LocalObject cookie);
void deactivate(string category);
};
};
Note that ServantLocator is a local interface. To create an actual implementation of a servant locator, you must define a class that is derived from Ice::ServantLocator and provide implementations of the locate, finished, and deactivate operations. The Ice run time invokes the operations on your derived class as follows:
locate
Whenever a request arrives for which no entry exists in the active servant map (ASM), the Ice run time callslocateand supplies theCurrentobject for the request. The implementation oflocate(which you provide as part of the derived class) is supposed to return a servant that can process the incoming request. Your implementation oflocatecan behave in three possible ways:
1. Locate an existing or instantiate a new servant, and return this servant for the current request. In this case, the Ice run time dispatches the request to this servant
2. return null, which is equivalent to throwing ObjectNotExistException
3. throw a system exception such as ObjectNotExistException, OperationNotExistException and FacetNotExistException
You can also throw user exceptions fromlocate. If the user exception is in the corresponding operation's exception specification, that user exception is returned to the client. User exceptions thrown bylocatethat are not listed in the exception specification of the corresponding operation are also returned to the client, and then thrown in the client asUnknownUserException. Non-Ice exceptions are returned to the client asUnknownException.
Thecookieout-parameter tolocateallows you to return a local object to the object adapter. The object adapter does not care about the contents of that object (and it is legal to return a null cookie). Instead, the Ice run time passes whatever cookie you return fromlocateback to you when it callsfinished. This allows you to pass an arbitrary amount of state fromlocateto the corresponding call tofinished.
finished
If a call tolocatehas returned a servant to the Ice run time, the Ice run time dispatches the incoming request to the servant. Once the request is complete (that is, the operation being invoked has completed), the Ice run time callsfinished, passing the servant whose operation has completed, theCurrentobject for the request, and the cookie that was initially created bylocate. This means that every call tolocateis balanced by a corresponding call tofinished(provided thatlocateactually returned a servant).
If you throw an exception fromfinished, the Ice run time propagates the thrown exception back to the client. As forlocate, you can throw user exceptions fromfinished. If a user exception is in the corresponding operation's exception specification, that user exception is returned to the client. User exceptions that are not in the corresponding operation's exception specification are also returned to the client, and then thrown by the client asUnknownUserException.
finishedcan also throw run-time exceptions. However, onlyObjectNotExistException,OperationNotExistException, andFacetNotExistExceptionare propagated without change to the client; other run-time exceptions are returned to the client asUnknownLocalException.
Non-Ice exceptions thrown fromfinishedare returned to the client asUnknownException.
If both the operation implementation andfinishedthrow a user exception, the exception thrown byfinishedoverrides the exception thrown by the operation.
deactivate
Thedeactivateoperation allows a servant locator to clean up once it is no longer needed. (For example, the locator might close a database connection.) The Ice run time passes the category of the servant locator being deactivated to thedeactivateoperation.
The run time callsdeactivatewhen destroying the object adapter to which the servant locator is attached. More precisely,deactivateis called when you calldestroyon the object adapter, or when you calldestroyon the communicator (which implicitly callsdestroyon the object adapter).
Once the run time has calleddeactivate, it is guaranteed that no further calls tolocateorfinishedcan happen, that is,deactivateis called exactly once, after all operations dispatched via this servant locator have completed.
This also explains whydeactivateis not called as part ofObjectAdapter::deactivate:ObjectAdapter::deactivateinitiates deactivation and returns immediately, so it cannot callServantLocator::deactivatedirectly, because there might still be outstanding requests dispatched via this servant locator that have to complete first — in turn, this would mean that eitherObjectAdapter::deactivatecould block (which it must not do) or that a call toServantLocator::deactivatecould be followed by one or more calls tofinished(which must not happen either).
It is important to realize that the Ice run time does not "remember" the servant that is returned by a particular call to locate. Instead, the Ice run time simply dispatches an incoming request to the servant returned by locate and, once the request is complete, calls finished. In particular, if two requests for the same servant arrive more or less simultaneously, the Ice run time calls locate and finished once for each request. In other words, locate establishes the association between an object identity and a servant; that association is valid only for a single request and is never used by the Ice run time to dispatch a different request.