To participate in a structured conversation, participants need to understand what is required of them, and what they can expect from their conversation partners. For example, a service consumer needs to know that it can initiate a conversation any time by sending a message. It also needs to know whether it can safely resend a request message, and whether it can expect exactly one response message or whether it has to be prepared to deal with duplicate response messages. The service provider in turn must be able to receive a request message at any time and be prepared to process it.
A conversation policy gives a precise description of all legal message exchanges that make up a specific type of conversation. The policy establishes a contract between conversation participants, which they are expected to abide by.
A conversation policy defines the following elements:
- Participant Roles - A conversation takes place between multiple participants, each of which plays one or more roles. For example, a buyer may have a conversation with a supplier of goods while another conversation may involve a meeting requestor, a meeting coordinator, and a meeting participant. One physical entity (a business, a human being, or a computer system) might play more than one role in a conversation or take part in multiple conversations at the same time. For example, the meeting requestor might also be a meeting participant. Likewise, the conversation may allow multiple participants playing the same role, e.g. multiple people acting as meeting participant.
- Message Types - Participants communicate by exchanging messages. They not only have to understand the message content, but also the message's role in the conversation, i.e., the semantics of the message. For example, a Schedule a Meeting conversation may use the message types Request Availability, Available Times, Meeting Invite, Confirmation, and Meeting Reminder. Participants must be able to understand which type of message they receive so they can continue the conversation appropriately.
- Protocol - The protocol specifies the valid ordering of message types between the participants, i.e., which messages can be sent by whom, and in which order. For example, the meeting coordinator cannot send out a confirmation of the meeting time until everybody has provided their availability (or the deadline passed), whereas the meeting participants should expect to be asked about their availability at any time and respond appropriately. The protocol can include repeating messages or messages sent in any order, e.g. when a participant subscribes to be updated continuously.
If an instance of a conversation fulfills the rules established by a conversation policy, we call that conversation legal with regards to that policy. Most conversation policies allow many legal instances. For example, the conversation to setup a meeting doesn't require a particular order among the meeting reminder messages to the participants, making any interaction that sends messages to all meeting participants in any order legal.
A Simple Conversation
Let's consider a simple purchasing scenario, which consists of the participants Buyer and Supplier. They exchange the message types Order to place an order, Shipment Notice to indicate the ordered goods have been shipped, Invoice, and Payment. The protocol for the conversation Purchase Transaction specifies that the Supplier sends an Invoice only after receiving an Order message from the Buyer. Every Invoice message must be followed by a Payment from the Buyer, who in turn must be assured that the Order ultimately leads to a Shipment Notice.
However, the conversation policy may not specify an order between the Shipment Notice and Invoice messages, allowing the supplier to send these messages in either order, e.g. the Supplier could invoice before the Shipment Notice. When the Buyer has to follow the Invoice with a Payment will usually be specified in the terms and conditions. If the Payment is not received, the Supplier can send a Reminder and possibly a Request for payment. The conversation policy can also define whether the Buyer is allowed to send a Payment before the Invoice is sent, e.g. to make a prepayment or down-payment. One can quickly see that a relatively simple conversation has to deal with a variety of conditions.
For now we assume that a Payment follows an Invoice, but that Invoice and Shipment Notice are independent. We also omit error conditions, such as a missing payment. The following diagram formulates these constraints as a simple process on the right-hand side. The process diagram, which intentionally does not use any standard notation, contains activity elements indicating sending a message to or receiving a message from the conversation partner. The process begins by receiving an Order message, followed by two parallel execution streams, one of which sends the Shipment Notice and one consisting of sending an Invoice and receiving a Payment. The process only shows the activities relevant to the conversation and omits steps like actually shipping the goods, processing payments, etc.
The left side of the diagram depicts all legal conversation instances of this policy.
The process defines the protocol, i.e. the valid sequences in which messages can be sent and received. The supplier's implementation may be more strict than the protocol allows, e.g. the actual implementation may be hard-wired to always send the Invoice message before the Shipment Notice. Nevertheless, the buyer has to be prepared to receive the messages in either order, because the published conversation policy, which is the contract between the participants, allows this. The supplier thus reserves the right to change its implementation in the future thanks to the separation of interface and implementation and the low coupling specified in the contract. The relationship between the declared conversation policy and the actual supplier-side implementation mimics the relationship between a service interface and the service implementation: Service consumers have to abide by the rules of the service interface, not a specific implementation.
Robustness Principle (Postel's Law)
One of the most widely used and robust protocols is TCP - The Transmission Control Protocol that is part of the TCP/IP stack, which forms the basis for pretty much all Internet traffic. When editing the TCP Specification [Transmission Control Protocol], Jon Postels specified the Robustness Principle:
TCP implementations should follow a general principle of robustness: be conservative in what you do, be liberal in what you accept from others.
In our example, the robustness principle could mean that the Supplier can accept Payment messages before the Invoice message was sent, even though the conversation policy does not allow this.
Mapping the Conversation Policy to the Participants
Each conversation participant projects the conversation policy onto its own viewpoint of the conversation. For example, the buyer’s view if the above conversation prescribes that it has to initiate the conversation by sending an Order message, and has to be ready to receive two messages in either order next. When it receives the Invoice message, it has to reply with a Payment message.
picture
Describing Conversations
Conversation protocols can fundamentally be described statically or dynamically. Static descriptions are defined and known to the participants a priori, i.e. before they engage in the conversation. This allows participants to understand the rules of engagement beforehand and also enables code generation to automatically implement participant-side workflow that is guaranteed to be in line with the conversation policy. Once, the policy is defined, though, it cannot easily be changed.
Dynamic protocol definitions only exist once the conversation has started. This implies that at least one participant knows up-front how to initiate the conversation. Subsequently, a conversation participant can describe allowed next steps as part of the message being sent to other participants. Naturally, this approach provides the loosest coupling, but it does not support code generation or static validations.
Conversation protocols can be described using the following methods:
- Enumeration. If the conversation policy is fairly strict, the number of legal conversations may be small. In these cases, the policy can simply enumerate all legal conversations, similar to the example above. While conceptually simple, this approach quickly reaches its limitations. For example, if the consumer in a request-response conversation is allowed to resend messages, enumerating all possibilities becomes tedious at best, and impossible for the general case. This limitation of the enumeration approach is particularly severe because fewer constraints are a desirable feature of a loosely coupled conversation policy. Therefore, we do not list this option as a general pattern that is observed in practice
- Choreography. Considering the conversation from a third-party perspective, one can describe the protocol as an abstract process, which defines which messages can be sent by which participant. The process template considers all conversation participants as equal parties, essentially viewing the conversation from the perspective of a neutral observer.
- Orchestration. In many conversations one participant plays a central role, meaning all other participants only communicate with this participant, but not with each other. This s for example the case in two-party conversations where a service consumer interacts with a service provider. Because all message run through this participant, its view of the conversation defines the whole conversation. Thus a process template used by this participant can now serve as the conversation protocol definition for all participants, albeit from the perspective of the orchestrator.
- Hypermedia State. Instead of defining the conversation protocol up-front, a service provider can inform a service consumer of the legal next messages using a dynamic protocol. If messages are using the HTTP protocol, a natural way to embed this information in form of URI's.
Error States
When looking at conversations, we often look at the "happy path", i.e. the sequence or sequences of steps that accomplish the primary objective of the conversation. As with all activities, naturally many things can go wrong: expected responses are not received, have the wrong format, or come in the wrong order. Also, the engine executing the process behind the conversation might crash and have to pick up at a later place.
Composing Conversations
Many conversations have to deal with multiple aspects at once: they may have to discover a service provider, authenticate to it, then initiate a conversation, while renewing a Lease to keep using resources. It is helpful to consider the elements of such conversations separately. The conversational elements can be composed in multiple ways:
- Sequencing: One element of the conversation may follow another, e.g. a Asynchronous Request-Response may follow a Dynamic Discovery.
- Expansion: A single message in one conversation may in fact be a sequence of messages that are part of another, more detailed conversation. For example, a single "message" in a Relay conversation could be a Request-Response with Retry.
- Overlay: Some conversations occur concurrently, for example a patternRef name="SubscribeNotify"/> conversation may need a patternRef name="Lease"/> renewal.
Conversations at multiple levels
Different layers of the communication can use different conversation protocols. For example, a TCP stack implements a reliable protocol over asynchronous IP packets by using Request-Response with Retry while an application might hold a Asynchronous Request-Response conversation on top of TCP, e.g. by using two separate HTTP connections. Lastly, the client application might not actually be able to process response messages asynchronously, but rather uses Polling to obtain the response from the interface layer (see figure).
This (quite realistic) scenario employs three different conversations that all work together to move data between A and B. It is therefore essential that whenever we talk about conversation protocols that we state the context, i.e. the communications layer, that we refer to. By default, we assume that the conversation occurs over a common messaging system that is implemented using common protocols such as HTTP or that is abstracted behind common APIs such as JMS, MSMQ or the like. These APIs or base protocols define what the application layer understands as "message" and therefore defines the context of the conversations. In this example, we would consider the conversation an Asynchronous Request-Response unless otherwise stated.