14.4 Example

  Previous section   Next section

To illustrate potential integration problems and the utility of adapters, we use a small client/server application from the telephone-based telecommunications domain that uses a signaling protocol called Signaling System 7 (SS7). We use the telecommunications domain because advances in this domain will be key elements in supporting the interstellar SW Web. The illustrative system contains two components, a monitor (MT) responsible for monitoring the signaling links of the space system and a manager (MG) component responsible for handling requests (from the monitor) to bring space links into service, inhibit links, and take links out of service.

Consider the services provided by the monitor component (see Listing 14.2).

Listing 14.2 Monitor Services
MT interface {
  Monitor-links();                // To monitor a link
  Inservice-result(result: int);  // Result of inservice request
  Inhibit-result(result: int);    // Result of inhibit request
  Outservice-result(result: int); // Result of outservice request

The monitor expects the services shown in Listing 14.3 to be defined in another component.

Listing 14.3 External Services
In-service(link-id: short int, time: long int);
Inh-service(link-id: short int, time: long int);
Out-service(link-id: short int, time: long int);

The manager component provides the services shown in Listing 14.4.

Listing 14.4 Manager Services
MG interface {
  Inservice(time-in: float, link-num: long int);
  Inhibit(time-inh: float, link-num: long int);
  Outservice(time-out: float, link-num: long int);

The manager also expects to send an integer result that indicates success or failure of the service request to the component that invoked the service. The underlying communication mechanism is asynchronous message passing. For this application we need two queues, one that holds messages traveling from MT to MG and another that holds messages traveling from MG to MT. The communication mechanism has an interface that looks like that in Listing 14.5.

Listing 14.5 Communication Interface
Message-Object interface {
Result create-queue(queue-id: int);
Result attach-queue(queue-id: int);
Result put-Msg(Msg);
Result get-Msg(Msg);

Integrating these components involves providing ways for these components to interact. Consider the "inservice" interaction. The service name and the signatures for MG and MT do not match: Component MT expects to send a short int to represent the link and a long int to represent the time, while component MG expects to receive a float to represent the time followed by a long int for the link number. The standard solution to this type of problem is to manually modify one of the component implementations to fix the mismatch.

Consider the same application with adapters. The component signatures are as shown previously, but we have one adapter associated with each component. In an adapter-based system, interaction between the client and the server is handled as follows. The client generates a request that is received by its adapter. The adapter takes the request and forwards it to the server's adapter. Finally, the server adapter sends the request to the actual server. One purpose of these adapters is to handle potential mismatches in the communication. In the previous example we have a simple mismatch in the data types and ordering of the parameters. If code to handle the mismatch could be made part of the client's adapter, then neither the client nor the server would have to be modified to correct the mismatch; the adapters would handle it. The mismatch can be described using a notation like Nimble (Purtilo 1991). Nimble provides a way to describe both the formal (server) and actual (client) interfaces, as well as a map between them. If the map is well formed, Nimble produces code that performs the mapping.

In Nimble, we describe the formal parameters, the actual parameters, and then the map between them (see Listing 14.6).

Listing 14.6 Nimble Example
SERVICE In-service
ACTUAL PATTERN: link-id: short int, time: long int
FORMAL PATTERN: float, long int
NIMBLE MAP: FLOAT(time), LONG(link-id)

This is a relatively simple map that swaps the actual parameters and coerces their types to match the formal parameters. In addition to providing built-in coercions, Nimble also provides ways to describe masking out of parameters, introduction of new parameters (with default values), and adding user-defined coercion routines. In an adapter-based system, this specification defines a map between what this adapter receives and what is sent to the manager component's adapter.

Nimble provides a nice way to describe data heterogeneity (parameter mismatches) but cannot describe mappings between interaction mismatches. Consider the situation where we introduce a different server that meets the same functional requirements (adding, removing, and inhibiting links) but does not return a result value to the client. If the client waits for this value to return, as is done in many client/server interactions, no further progress will be made in the client. Obviously, one solution is to modify the client so that this expectation is removed; a solution that requires no change to the client is one in which the adapter generates a return value after the request is sent to the server. Describing both the mismatch and the solution requires a richer language. Contributing such an improved language is one of the research tasks.


Part IV: Applications of XML