Component implementation guidelines

The following guidelines may be useful when you are writing components that support automatic failover.

The component should not retain conversational state in server memory (component instance variables), since the conversational state cannot be restored when a remote method call fails over from one server to another.

The following example shows why this would not work:

  1. The client calls method A on component C on Server1. Method A retains some state in the instance in Server1’s memory.

  2. The client calls method B on the same component. Server1 has failed, so the client transparently fails over to Server2 and calls method B on a newly instantiated instance of component B in Server2. Since method A has not been called on this instance, it does not hold the saved state.

If you must save state between calls, consider saving it in a database. For example, in an Internet shopping application, a “shopping cart” might be represented by a database entity, and every method call on the ShoppingCart component can save the appropriate changes to the database.

In other cases, you might want to code the client to use IDL structure and sequence types to pass a list of values to a single component method, instead of passing each value in a separate call and having the component attempt to collect the list of values using conversational state. This approach also reduces network traffic, and can greatly improve response times.

Duplicate database inserts or updates can result from the use of automatic failover, as in the following example:

  1. The client calls method insertStuff on component C on Server1.

  2. The insertStuff method inserts a record into a database.

  3. The transaction is committed.

  4. The server crashes before sending the reply message over the network to the client.

  5. The client transparently fails over, and calls method insertStuff on a new instance of component C on Server2.

  6. The insertStuff method inserts a new (duplicate) record into the database.

    Everything works this time, but we now have a duplicate record in the database.

A simple design approach can help avoid such problems. Add a method to component C to generate a new ID for insertion: for example, newStuffId:

  1. The client calls newStuffId to get a new unique ID. If you do not permit gaps in the ID numbering sequence, you cannot use this approach.

  2. The client then calls insertStuff, passing the StuffId as a parameter.

  3. insertStuff verifies that a record for that StuffId has already been inserted (or the database insert fails if StuffId is a unique key in the database).

    Although insertStuff has been called twice, only one database change has been made.

A component that supports automatic failover can use other components or resources that do not directly support automatic failover.