Refactoring SOAP MEPs for Asynchronous Use

Introduction

This document presents an attempt to refactor the existing SOAP request/response and SOAP response MEPs in order to better support asynchronous interactions.  The basic approach is to take at face value the idea that all MEPs are build up from one-way message exchanges.  In particular, a request-response MEP consists of the one-way exchange of a request message, followed (normally) by the one-way exchange of a response.

Notation

In the following text, the term reply means a successful application-level response, to be sent to the WSA [reply endpoint].  The term fault refers to an application-level fault to be sent to the WSA [fault endpoint].  The term response means reply or fault.  The term failure means a transport-level failure.

MEPs are referred to by their WSDL 2.0 names, with the understanding that the same analysis may be applied to WSDL 1.1 MEPs.

Motivating Use Cases

The analysis given here is motivated by several specific use cases gathered as part of the work of the Async Task Force.  While these clearly do not cover every possible mode of asynchronous interaction, it is hoped that a framework powerful enough to handle all of them cleanly will also be able to handle a wide variety of other cases.

The use cases are:

·        The existing synchronous HTTP request-response.  Clearly, any re-analysis of MEPs must handle existing behavior identically to the current formulation.

·        (asynchronous request-response over HTTP) HTTP Request-Response in which at least one of {[reply endpoint], [fault endpoint]} is directed at a third party, possibly using a transport other than HTTP.  Particularly interesting is the subcase in which one of the endpoints is the HTTP response channel (i.e., the “anonymous” endpoint address) and one is not.

·        Request-response using pure one-way messaging.

·        Client-server reversal over an intermittent connection.  In this case, an intermittently connected “server”, for example a cell phone, polls a “client” for SOAP requests, by sending HTTP requests to an HTTP server.  The resulting HTTP response will contain a SOAP request message.  The “server” then formulates a SOAP response and sends it to the “client” via an HTTP request.  The application-level flow from “client” to “server” and back is thus exactly out of phase with the transport-level flow.

·        Intermittent connection with batching.  Taking the previous scenario one step further, there is no reason that the HTTP response to the poll from the server could not contain several SOAP requests.  Similarly, the polling HTTP request might contain one or more SOAP responses to previous requests.  Going one step further yet, there is no reason why a transport-level HTTP message, whether request or response, might not contain any combination of SOAP requests, responses or pure one-way messages.  In such a scenario, the application-level and transport-level flows are completely independent.

All of these cases may be handled fairly uniformly if an application-level request-response MEP is broken into its two component messages instead of being treated as a single unit.  In particular, the existing HTTP request-response binding is redefined as the combination of two bindings:  SOAP over HTTP request and SOAP over HTTP Response (essentially the existing SOAP response MEP).  The ability of HTTP to perform a request-response as a single interaction then becomes a special feature of the HTTP binding (and possibly of similar bindings), which may be used if certain conditions are met.

All currently-defined WSDL MEPs, and many possible variations, may be defined as combinations of one-way message exchanges.  Given this, there is no need for a SOAP request-response MEP per se.  Instead:

·        MEPs such as the existing WSDL MEPs are defined in terms of one-way message exchanges.  This captures the distributed state machine behavior of the MEPs, without committing to SOAP or any other particular messaging mechanism.

·        SOAP bindings define how to exchange a single one-way message over various available transport mechanisms.  As mentioned above, HTTP requests and HTTP responses are treated as separate mechanisms for this purpose.

·        Particular bindings may define special handling for one or more MEPs.  For example, HTTP provides special support for request-response and robust in-only.

Distributed State and One-way Exchanges

The present definition of SOAP request-response relies on a distributed state machine in which the client and server each pass from an initial state into a “sending+receiving” state.  This allows for streaming, that is, the ability of a server to begin sending back a response before it has read all of the corresponding request.

In the present treatment, the receipt of a request and the sending of a response are treated as separate message exchanges, each with its own distributed state.  The default assumption in such a case is that the two exchanges may occur completely independently.  Ordering is imposed externally by the functional requirement that a server must know what sort of response to send, and where to send it, before sending it.  This in turn depends on having received at least part of the request.  It will be shown that the distributed state machines implied by the two approaches are essentially equivalent, though their non-normative interpretations are somewhat different.

State of a one-way message exchange

A one-way message exchange is modeled as the combination of a sender and a receiver, each with an almost trivial state machine.  The sender begins in the initial state and transitions to either the success state or the failure state, depending on whether it regards the message as having been successfully sent.  Similarly, the receiver begins in its initial state and may either remain in that state or transition to its success or failure state.  Failure here is to be interpreted as a transport-level failure, independent of an application-level failure indicated by a fault response.  A fault may be successfully transmitted; a successful response may fail to be transmitted, and so forth.

All six possible combinations of the above are allowed, reflecting the possibility that the sender and receiver may differ as to whether the message exchange was successful:

Final sender state

Final receiver state

Interpretation

Success

Initial

Message was sent, but never arrived (e.g., fire-and-forget to disabled receiver)

Success

Success

Message successfully sent and received

Success

Fail

Message was sent, but an error occurred during receipt (e.g., fire-and-forget with error on receiving end)

Fail

Initial

Sending failed, receiver not reached (e.g., network down)

Fail

Success

Message was put on wire and received, but failure occurred on sending end afterwards (e.g., TCP connection was dropped at just the wrong time)

Fail

Fail

Message failed to arrive, and both parties are aware of this.

Initial

Success

Disallowed.

Initial

Fail

Disallowed.

The WSDL In-Out defined in terms of message exchanges

The existing SOAP request-response MEP involves two parties: the client and the server.  In the fully general asynchronous case, there are actually four parties:

A request-response MEP consists of

·        a message exchange from the server to the [reply endpoint]

·        a message exchange from the server to the [fault endpoint]

As these are defined as occurring in parallel, streaming is allowed and is, in fact, the default behavior.

The state of the server can be considered as the product of the states of the receiving end of the request channel, the sending end of the reply channel, and the sending end of the fault channel.  From this perspective, it does not matter where the opposite ends of these channels are located, though this information can be important in handling the binding-level details of particular cases.

If we denote the initial, success and failure states by i, s and f, we can describe the overall state of the server by a triple containing the states of the request receiver, reply sender and fault sender.  For example, the initial state is (i, i, i), while the state in which a request has been received and a reply successfully sent is (s, s, i).  Given that the server may not try to send both a fault and a reply, not all of the 27 possible combinations are allowed, and those that are allowed break down into four equivalence classes.

These correspond to the Init, Success, Fail and Sending+Receiving states of the server in the present definition of SOAP request-response, with corresponding transitions (technically, the SOAP request-response state diagram is the quotient of the server state diagram described here, modulo the equivalence relation defined above).

 

In-out in the usual synchronous case

In the well-known synchronous case, the client, [reply endpoint] and [fault endpoint] are identical, or, more precisely, the [reply endpoint] and [fault endpoint] are identical and are at the same end of a bidirectional channel as the client.  In this case, the client state can be considered as the product of the sending end of the request channel and the receiving end of the reply and fault channels.  Again, only one of the reply and fault receivers will receive a message, and again the state diagram gives rise to the state diagram in the existing SOAP request-response MEP, modulo the appropriate equivalences.

In-out in asynchronous cases

The server state diagram given above was derived from combining the state diagrams of the three component endpoints, and therefore works equally well for the typical asynchronous case in which the reply and fault destinations are not the client.  In cases where two roles are combined, but not all three (for example, only faults are directed back to the client, or faults and replies are directed to the same third party), combined state diagrams can be derived similar to those derived for the server and for the synchronous client.

Other WSDL MEPs

Two other WSDL MEPs are of particular interest: in-only and robust in-only.  The out-in, out-only and robust out-only patterns are here considered as equivalent to their oppositely oriented counterparts, at least from the point of view of transporting messages.

The in-only MEP is simply a single message exchange as defined above.  The robust in-only MEP is a single inbound message exchange in parallel with an optional message exchange from the receiver to the [fault endpoint].  As the state diagrams for this case are essentially simplified versions of those for in-out, we do not discuss them in detail here.

The need for acknowledgements

Consider an instance of the in-out MEP in which the request is sent over a two-way synchronous protocol such as HTTP, the [reply endpoint] is a third party and the [fault endpoint] is anonymous, that is, directed back to the client (There is a similar case where the reply is anonymous and the fault is not.  We choose this case solely for concreteness).

After the reply is sent, the client needs to know whether the operation succeeded or not.  If the operation fails, the client will receive a fault through the anonymous channel and know that the operation has failed.  But if the operation succeeds, the server will send the reply to the reply endpoint, and, at least at first glance, is not required to do anything further.  Apparently, the client will continue to hang, waiting for a possible fault that will never be sent, or will time out after some arbitrary interval, with no way of knowing whether the request message even arrived.  This would be unfortunate, since the server has it in its power to send back a positive acknowledgement of receipt.

If possible, this requirement to send acknowledgement should be pushed to the transport binding level, rather than redefining the server’s state diagram to include acknowledgement.  Fortunately, this is possible for transport bindings that follow one additional rule:  The receiver of a request message sent over a two-way synchronous protocol cannot enter the “success” state without first sending a message over the response channel.  This message could be a reply, a fault, or a binding-specified acknowledgement message.  Note that it is the transport-level request that must be acknowledged, an important distinction in cases where the application-level flow is out of phase with or completely decoupled from the transport-level flow.

With this rule in place, the server will always receive either a fault or an acknowledgement.  The acknowledgment is (in this case) that the request was received and no application-level fault was produced.  It does not guarantee that the reply was successfully delivered to its ultimate recipient.

HTTP Bindings

With MEPs moved out of the SOAP layer, the job of a binding is simply to specify how a single message exchange is to be done.  In the case of a two-way synchronous protocol such as HTTP, this means defining two bindings, one for sending a message over the request channel, and one for sending a message over the reply channel.

SOAP over HTTP Request (POST)

This is essentially the request half of the current HTTP request-response binding, using POST to deliver a request, together with the requirement stated above that the recipient must send back some sort of message before entering its success state.  In order to make pure acknowledgements possible in the case where neither a reply nor a fault is to be returned, the SOAP over HTTP Request binding defines an acknowledgment as an empty message with status code 202 (Accepted).  This means that, for example, a pure one-way message sent over HTTP will receive a 202 response.  In the case described above, with only [fault endpoint] anonymous, the client will receive either a fault or a 202 acknowledgment in response to its request.

SOAP over HTTP Request (GET)

In a request-response exchange consisting of an HTTP GET method and a SOAP response, the request may be seen as a separate entity.  This is the approach taken in the existing adjuncts specification, and it is compatible with the SOAP over HTTP response binding defined in the next section.  Alternatively, it can be seen as a specially encoded SOAP message.  Conversely, at least some SOAP requests can be bound to specially constructed URLs to be used with an HTTP GET.

The decision as to whether to bind a request as a GET or a POST may be deferred to run time, provided the server supports both bindings, depending on how complex the request content is.  A simple method invocation with no arguments (e.g., a getter) might typically be bound as a GET, while an invocation with large or highly structured arguments could be bound as a POST.

SOAP over HTTP Response

This is essentially the existing SOAP Response MEP, cast in terms of the one-way message exchange state machine defined above.

Non-standard flows

It should be clear that, with the separated bindings defined above, the reversed flow of the intermittently connected cell phone can be modeled as

The completely decoupled case does not fall neatly into this pattern.  However, one could define a “batched” SOAP message format, with the body having multiple <soap:env> elements as children, and the transfer of a single batched message giving rise to the exchange of zero or more child messages.

Since the server state machine is already defined in terms of single message exchanges, it should work unchanged in such a scenario.