Chapter 3: Message Exchange Patterns, Topologies, and Choreographies


When designing messaging applications, it is necessary to consider how messages flow between the sender, any intermediaries, and the receiver (the previous chapter described these messaging participants). The welter of message exchange possibilities in a system can be described at varying levels of detail. These levels of detail are generally known as Message Exchange Patterns (MEPs), Message Topologies, and Message Choreographies. When viewed as a whole, these three levels of detail allow us to abstractly describe any messaging scenario. This chapter examines message exchange patterns, message topologies, and message choreog-raphies and how they are used to provide advanced functionality in our Microsoft Windows Communication Foundation (WCF) applications.

Message Exchange Patterns

The most granular level of detail we use to describe a message exchange is a Message Exchange Pattern (MEP). According to the W3C drafts (http://www.w3.org/2002/ws/cg/2/07/meps.html), a MEP is “a template that describes the message exchange between messaging participants.” The industry has generally accepted that a MEP is limited to one logical connection between one sender and one receiver. Since MEPs are a somewhat abstract concept, it is helpful to closely look at some real-world examples for clarification. Let’s examine the following phone conversation between me and a friend as we discuss a football game:

  1. I pick up my phone and dial Rusty’s phone number.

  2. Rusty picks up his phone.

  3. Rusty says, “Hello.”

  4. I say, “Did you watch the game today?”

  5. Rusty says, “Yep-it was awful. I can’t believe we didn’t win.”

  6. Rusty says, “They totally choked.”

The conversation continues

Steps 1 through 3 can be thought of as transmission-specific events (I call Rusty, and he acknowledges that he is ready to talk). In step 4, I send Rusty a message in the form of a question, and custom dictates that he should answer. In step 5, Rusty sends me a message in response to my question. Step 6 is an unsolicited message sent to me that may or may not solicit a response. The message correlation is implicit, since it is part of the natural flow of conversation. If this correlation weren’t assumed, I would have no idea exactly what he thought was awful; it might have been a sales call or a chess match.

In this scenario, both Rusty and I are free to talk at will (as shown in step 6), and we are even free to talk over one another. As we all know, this is the nature of most phone conversations. Not all phone conversations are two-way; some are one-way. A one-way conversation might happen by design, as in a shareholder conference call, or because one party terminates the call before a response can be sent. Let’s look at another phone call to illustrate:

  1. Lewis (my boss) picks up his phone and dials my phone number.

  2. I pick up my phone and say, “Hello.”

  3. Lewis says, “You’re doing a great job. I’m giving you a 100 percent raise, effective immediately.”

  4. Lewis then hangs up his phone.

  5. I call Lewis back.

  6. Lewis answers his phone.

  7. I say. “That is too generous; I will accept only a 50 percent raise.”

  8. I hang up the phone.

  9. Lewis calls me back.

  10. I answer my phone.

  11. Lewis says, “A 100 percent raise is final, and I am throwing in a blue Porsche 911 Turbo to make sure that you can get to engagements faster.”

  12. Lewis then hangs up his phone.

In the preceding scenario, I can respond, but Lewis is so intent on giving me raises and perks that he isn’t listening for my response. I have to call him back to further the discussion. Conceptually speaking, responses in a message exchange require the sender to listen for a response either in an existing connection or in a new connection.

Conversations can even fit a more rigid model. Consider the communications between a commercial airline pilot and a radio tower. If you have ever listened to these communications, the structure is obvious:

  1. The control tower calls to the pilot: “Contoso 437, turn to 180 degrees, 300 knots, descend to 10,000 feet.”

  2. The pilot responds: “Contoso 437, turning to 180 degrees, 300 knots, descending to 10,000 feet.”

In this scenario, the heading change request initiated by the tower demands a response. If no response is transmitted from the plane, the now-annoyed air traffic controller will repeat the command until a proper response is transmitted, or some other action is taken. Furthermore, this protocol demands that the pilot not interrupt the tower while the tower is communicating.

These simple analogies go a long way to describing the interactions between messaging participants in a service-oriented application. In general terms, MEPs are classified according to how participants interact with each other and, more specifically, the number of responses that are allowed and whether those responses require new logical connections between the sender and receiver. While there might be a womptillion different ways to talk on the phone or on a radio, there are generally three types of MEPs in the service-oriented world: datagram, request-response, and duplex.

The Datagram MEP

Figure 3-1 illustrates the datagram MEP. Also called simplex, this MEP represents a one-way message send, or a fire-and-forget send. Messages sent using this MEP are called datagrams. Conceptually, a datagram is similar to leaving a voice-mail message in the sport of phone tag. While you are leaving the voice-mail message, you probably don’t expect a response during the call. You might, however, expect a response in the form of a return call. Responses to datagram messages are considered out of band. In other words, responses to datagrams require a new connection between a sender and a receiver.

image from book
Figure 3-1: The datagram MEP

Datagrams and WSDL

A datagram MEP is expressed in Web Services Description Language (WSDL) as an operation that contains a wsdl:input element and no wsdl:output elements. For example, the following WSDL snippet describes one operation that accepts input only and is therefore an operation that uses the datagram MEP:

 ... <wsdl:portType name="ISomeContract" ...>     <wsdl:operation name="SomeOperation">       <wsdl:input wsa10:Action="urn:SomeActionInput" ... />     </wsdl:operation> </wsdl:portType> ...

Datagrams and WCF Contracts

Creating a WCF application that uses the datagram MEP is fairly straightforward. As always, we start with the contract:

 // File: Contract.cs using System; using System.ServiceModel; using System.ServiceModel.Channels; [ServiceContract(Namespace="http://wintellect.com/SomeContract",   Name="ISomeContract")] public interface ISomeContract {   [OperationContract(Name="SomeOperation",                      Action="urn:SomeActionInput",                      IsOneWay=true)]   void SomeOperation(Message message); }

There are two important things to notice in this example: the void return type on the SomeOperation method and the IsOneWay instance property on the OperationContractAttribute type.

The void Return Type   Because we are using a C# interface method to describe a datagram messaging operation, we need to use a return type that reflects this one-way messaging operation. Methods that are used to describe datagram messaging operations must have a void return type. Specifying some other return type results in an InvalidOperationException thrown by the WCF runtime during the verification of the contract.

The OperationContractAttribute’s IsOneWay Property   Defining an interface method with a void return type is not enough when defining a datagram operation. Consider the following contract:

 // File: Contract.cs using System; using System.ServiceModel; using System.ServiceModel.Channels; [ServiceContract(Namespace="http://wintellect.com/SomeContract",   Name="ISomeContract")] public interface ISomeContract {   [OperationContract(Name="SomeOperation",                      Action="urn:SomeActionInput",                      ReplyAction="urn:SomeActionOutput")]   void SomeOperation(Message message); }

This contract can ultimately be rendered in WSDL as follows:

   <wsdl:portType name="ISomeContract" ...>     <wsdl:operation name="SomeOperation">       <wsdl:input wsaw:Action="urn:SomeActionInput" .../>       <wsdl:output wsaw:Action="urn:SomeActionOutput".../>     </wsdl:operation>   </wsdl:portType>

The presence of the wsdl:output element indicates to the sender that a reply will follow the message send. Since the return type of our interface method is void, the message will have an empty <Body> element. Even though there is no data sent in the body, this is still a reply. It is important to note that the WCF runtime must generate this reply and requires processing overhead every time a valid message is received. In WCF, the only way to remove this reply message is to set the IsOneWay instance property of the OperationContractAttribute to true. If this property is set to false by default, the setting makes the operation use the Request/Reply MEP (discussed shortly).

Error Handling Considerations

The datagram MEP introduces an interesting service-oriented twist in the area of error handling. As you’ll see in Chapter 4, “WCF 101,” errors may be serialized as SOAP faults, and these faults can be sent to the specified endpoint. With the datagram MEP, the sender is not under any obligation to listen for these faults. If the sender wants to receive these fault messages or have them sent to another endpoint, the sender must specify that endpoint in the <FaultTo> header block of outbound messages. It is then the receiver’s responsibility to make its best effort to send these fault messages to the specified endpoint.

HTTP and the Datagram MEP

All transports support the datagram MEP, but some transports, like HTTP and HTTPS, have response mechanisms built into the transport. When messages are sent over one of these protocols, the sender expects to receive a reply, and the receiver expects to send a reply. For example, when we make an HTTP request for a Web page, we expect one HTML reply. Likewise, the Web server expects to be able to send the HTML reply to the client after it receives a request for a resource. HTTP replies are transmitted via the transport backchannel. For the purposes of this discussion, it is permissible to think of this backchannel as a listener that stops listening after the reply has been transmitted.

In WCF, when we send a datagram via HTTP, we are sending data over HTTP, and the reply is an HTTP response code of 202.[1] In general, when a datagram message is sent using a transport that demands these built-in acknowledgment mechanisms, the response contains a transport-specific acknowledgment and no message-specific information. The following is an example of the response to a datagram sent over HTTP:

 HTTP/1.1 202 Accepted Content-Length: 0 Server: Microsoft-HTTPAPI/1.0 Date: Sun, 25 Feb 2007 17:01:36 GMT

WCF applications that receive datagrams over HTTP send the 202 reply upon receipt of the datagram but before processing the datagram. This optimization means that the client does not wait unnecessarily for the transport reply, and the exchange is as close to one-way as possible.

The Request/Reply MEP

In a broad sense, the Internet is built on the Request/Reply MEP (also referred to as half-duplex). We have come to expect that a single Web page request will yield one HTML reply. If we would like to see another Web page, we initiate another Web request. In other words, the reply to our request is in band. Figure 3-2 conceptually illustrates the Request/Reply MEP.

image from book
Figure 3-2: The Request/Reply MEP

Note 

The request/reply MEP is so pervasive that we hardly notice when we are using it. For the most part, our experience has conditioned us to think in terms of request/reply. For example, most of our component-based frameworks require us to call a method and wait for that method to return. Many distributed component frameworks (like DCOM) reinforced this conditioning, because these frameworks allowed us to call a method and wait for a response. As a result of our conditioning, many of us will default to the request/reply MEP when first working with WCF. I encourage you to “free your mind” from this default MEP by forcing yourself to consider the other MEPs that are possible in WCF. Doing so will open the door for more advanced functionality and higher performance by reducing bandwidth use in your applications.

Request/Reply and WSDL

Request/Reply MEPs are expressed in WSDL as an operation that has wsdl:input and wsdl:output elements. For example, the following WSDL snippet describes a Request/Reply MEP:

 ... <wsdl:portType name="ISomeContract" ...>     <wsdl:operation name="SomeOperation">       <wsdl:input wsaw:Action="urn:SomeActionInput" ... />       <wsdl:output wsaw:Action="urn:SomeActionOutput" ... />     </wsdl:operation> </wsdl:portType> ...

It is important to note the order of the wsdl:input and wsdl:output elements in this WSDL snippet. The order of these elements dictates that an input message must be received before an output message can be sent.

Request/Reply and WCF Contracts

WCF operation contracts use the Request/Reply MEP by default. Any return type that is considered serializable by WCF can be specified as a return type. (Chapter 9, “Contracts,” discusses data and message serialization.) For example, the following contract uses Request/Reply:

 // File: Contract.cs using System; using System.ServiceModel; using System.ServiceModel.Channels; [ServiceContract(Namespace="http://wintellect.com/SomeContract",   Name="ISomeContract")] public interface ISomeContract2 {   [OperationContract(Name="SomeOperation",                      Action="urn:SomeActionInput",                      ReplyAction="urn:SomeActionOutput")]   Message SomeOperation(Message message); }

Transport Considerations

Some transports, like User Datagram Protocol (UDP) and MSMQ, are inherently one-way. As of the initial release of WCF, there is no out-of-the-box support for the Request/Reply MEP using MSMQ, and there is no support for UDP. Using the MSMQ transport with a Request/Reply MEP requires a connection between the sender and the receiver as well as a connection between the receiver and the sender. As a result, a custom channel is also required. We will examine how channels work in Chapter 6, “Channels.”

As you saw in Chapter 2, “Service Orientation,” there are several WS-Addressing header blocks that dictate where a receiving application should send a reply or fault. When using a transport like TCP, HTTP, or Named Pipes, the receiver can “send” the response over the transport backchannel. WS-Addressing states that the <ReplyTo> header block may be set to http://www.w3.org/2005/08/addressing/anonymous in these scenarios. This results in outbound messages that look like the following:

 <s:Envelope ... >   <s:Header>      <a:Action s:mustUnderstand="1">urn:SomeActionRequest</a:Action>      <a:MessageID>urn:12345</a:MessageID>   -  <a:ReplyTo>        <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>      </a:ReplyTo>      <a:To s:mustUnderstand="1">        net.tcp://localhost:8000/SomeOperation      </a:To>      </s:Header>      <s:Body>...</s:Body>   </s:Envelope>

And reply messages look like the following:

 <s:Envelope ... >   <s:Header>    <a:Action s:mustUnderstand="1">urn:SomeContractReply</a:Action>    <a:RelatesTo>urn:12345</a:RelatesTo>    <a:To s:mustUnderstand="1">      http://www.w3.org/2005/08/addressing/anonymous    </a:To>    </s:Header>    <s:Body>...</s:Body>  </s:Envelope>

The Duplex MEP

Duplexing is the ability to simultaneously transmit and receive messages and is the sort of interaction we have come to expect in a phone conversation. In a messaging application, the duplex MEP defines a set of operations that allow simultaneous message passing from the sender to the receiver and vice versa. Figure 3-3 illustrates the Duplex MEP.

image from book
Figure 3-3: The Duplex MEP

The Duplex MEP and WSDL

Because both the sender and the receiver can freely pass messages back and forth in the Duplex MEP, the WSDL associated with this MEP contains two operations. One operation (SomeOperation) represents messages inbound to the receiver, and the other (SomeCallbackOperation) represents messages traveling from the receiver to the sender.

   <wsdl:portType name="ISomeContract" ...>     <wsdl:operation name="SomeOperation">       <wsdl:input wsa10:Action="urn:SomeActionRequest" ... />     </wsdl:operation>     <wsdl:operation name="SomeCallbackOperation">       <wsdl:output wsa10:Action="urn:SomeCallbackRequest" ... />     </wsdl:operation>   </wsdl:portType>

In one sense, the duplex MEP is a combination of other MEPs. For example, the preceding WSDL snippet describes two datagram operations. In other words, a datagram can be sent from the sender to the receiver or vice versa. It is also possible that the messages sent between these participants rely on the request/reply MEP. Consider the following WSDL snippet:

   <wsdl:portType name="ISomeContract">     <wsdl:operation name="SomeOperation">       <wsdl:input wsaw:Action="urn:SomeActionRequest" ... />       <wsdl:output wsaw:Action="urn:SomeContractReply" ... />     </wsdl:operation>     <wsdl:operation name="SomeCallbackOperation">       <wsdl:output wsaw:Action="urn:SomeCallbackContractRequest" ... />       <wsdl:input wsaw:Action="urn:SomeCallbackContractReply" ... />     </wsdl:operation>   </wsdl:portType>

The SomeOperation operation describes the message sent from the sender to the receiver (urn:SomeActionRequest) and the message sent back to the sender (urn:SomeContractReply). The SomeCallbackOperation operation represents the message sent from the receiver to the client (urn:SomeCallbackContractRequest) and the message sent back to the receiver (urn:SomeCallbackContractReply).

The Duplex MEP and WCF Contracts

The WCF contract semantics for creating a Duplex MEP are a bit odd at first glance. As previously stated, duplex communication requires two contracts. By convention, the contract that describes the messages (and replies, if they are present) inbound to the receiver application are called service contracts, and contracts that describe messages sent from the receiver to the sender are called callback contracts. These two contracts are linked by the ServiceContractAttribute.CallbackContract property of the service contract, as shown here:

 // File: Contract.cs using System; using System.ServiceModel; using System.ServiceModel.Channels; using System.Runtime.Serialization; // the service contract looks the same as before, except // for the addition of the CallbackContract property // IsOneWay=true can also be set [ServiceContract(Namespace="http://wintellect.com/SomeContract",                  Name="ISomeContract",                  CallbackContract=typeof(ICallbackContract))] public interface ISomeContract3 {   [OperationContract(Name="SomeOperation",                      Action="urn:SomeActionRequest",                      ReplyAction="urn:SomeContractReply")]   void SomeOperation(Message message); } // No ServiceContract is necessary on the callback contract // IsOneWay=true can also be set public interface ICallbackContract {   [OperationContract(Name="SomeCallbackOperation",                      Action="urn:SomeCallbackContractRequest",                      ReplyAction="urn:SomeCallbackContractReply")]   void SomeCallbackOperation(Message message); }

Notice that the callback contract is referenced by the CallbackContract property of the ServiceContractAttribute type.

Tip 

When creating a duplex contract, it is typically a good idea to make the operations one-way. If the OperationContractAttribute’s IsOneWay property is not set, the message exchanges will be request-reply, and both participants will incur the overhead of creating reply messages. Setting the IsOneWay property to true reduces the overhead required for each messaging interaction.

[1] An HTTP status code of 202 is defined as follows: The request has been accepted for processing, but the processing has not been completed. The request might or might not eventually be acted upon, as it might be disallowed when processing actually takes place. There is no facility for resending a status code from an asynchronous operation such as this.

The 202 response is intentionally noncommittal. Its purpose is to allow a server to accept a request for some other process (perhaps a batch-oriented process that is run only once per day) without requiring that the user agent's connection to the server persist until the process is completed. The entity returned with this response should include an indication of the request's current status and either a pointer to a status monitor or some estimate of when the user can expect the request to be fulfilled.




Inside Windows Communication Foundation
Inside Windows Communication Foundation (Pro Developer)
ISBN: 0735623066
EAN: 2147483647
Year: 2007
Pages: 106
Authors: Justin Smith

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net