You may be tempted to write the life cycle operations as follows:
{zcode:slice} interface PhoneEntry { // ... idempotent void destroy(); // Wrong! }; interface PhoneEntryFactory { idempotent PhoneEntry* create(string name, string phNum) throws PhoneEntryExists; }; {zcode} |
The idea is that create
and destroy
can be idempotent operations because it is safe to let the Ice run time retry the operation in the event of a temporary network failure. However, this assumption is not true. To see why, consider the following scenario:
destroy
on a phone entry.ObjectNotExistException
to the client, which the Ice run time passes to the application code.ObjectNotExistException
and falsely concludes that it tried to destroy a non-existent object when, in fact, the object did exist and was destroyed as intended.A similar scenario can be constructed for create
: in that case, the application will receive a PhoneEntryExists
exception when, in fact, the entry did not exist and was created successfully.
These scenarios illustrate that create
and destroy
are never idempotent: sending one create
or destroy
invocation for a particular object is not the same as sending two invocations: the outcome depends on whether the first invocation succeeded or not, so create
and destroy
are not idempotent.