Asynchronous Request/Response Doubts

, Sep 6, 2005

Everybody and their mother agrees that doing web services RPC-style is a Bad Thing™, but not many people would extend that to request/response, which is a useful and common pattern in any sort of remote communication scenario. It’s not as easy as one might imagine, though, to find out how the SOAP, WSDL and WS-A specs and the rest of WS-* stack can be used to support this pattern when combined with asynchronous messaging.

One approach is to view request/response as a logical pattern, independent from the transport or transfer protocol being used. The WSDL 1.1 note at W3C — a note because WSDL 1.1 is not a W3C recommendation — has this paragraph, which supports this:

Note that a request-response operation is an abstract notion; a particular binding must be consulted to determine how the messages are actually sent: within a single communication (such as a HTTP request/response), or as two independent communications (such as two HTTP requests).

I haven’t been able to find an example of a binding that uses this; interestingly, though, the recently published IBM RAMP profile clarifies and extends the WS-I guidelines as follows, clearly supporting the WSDL 1.1 view:

In the context of the WS-I Basic Profile, the only reason the response message to an HTTP request would be empty is when the request message is a one-way message. However, the WS-Addressing specification introduces a wsa:ReplyTo SOAP header block that changes the nature of a request/response WSDL operation as it relates to the HTTP binding. If a request message includes a wsa:ReplyTo header that does not use the WS-Addressing Anonymous URI, then the response message is expected to be sent to the wsa:ReplyTo endpoint reference (EPR) rather than in the HTTP response message. Since the response message will not be sent in the HTTP response message, the HTTP response code on the original connection would be “202 Accepted”. While this doesn’t violate any WS-I Basic Profile requirements it is a change in behavior.

When viewed this way, a request/response interaction is a logical pattern, while its mapping to either a single request/response transport interaction or two one-way message transfers is a non-functional aspect. If it is, though, I still haven’t been able to find a formalized way to express this (i.e. indicate to the runtime that it is supposed to treat the request/response interaction this way).

There’s also a second approach: View a logical request/response interaction as something that is conceptually one level above what is described by WSDL. This seems to be supported by WSDL 2.0, not yet, but soon supposed to become a W3C standard (recommendation):

This binding extension specification provides a binding to HTTP of Interface Operation components whose {message exchange pattern} property has the value “http://www.w3.org/2005/08/wsdl/in-only”, “http://www.w3.org/2005/08/wsdl/robust-in-only” or “http://www.w3.org/2005/08/wsdl/in-out”. This HTTP binding extension MAY be used with other message exchange patterns such as outbound message exchange patterns, provided that additional semantics are defined, such as with an extension or with a Feature.
Each of the supported message exchange patterns involves one to two messages or faults being exchanged. The first is transmitted using an HTTP request, and the second is transmitted using the corresponding HTTP response. In cases where only one message is being sent, the message body of the HTTP response MUST be empty.

Based on this, the only correct way to map a WSDL 2.0 request/response to HTTP (as one example) is to use the synchronous transport/transfer mechanism. To support a logical request/response interaction, one can use two WSDL one-ways (where the rule of the empty response is obviously violated by the RAMP profile (which is not a problem since it relies on WSDL 1.1)). In this case, though, some other mechanism is needed to indicate to the runtime infrastructure that two one-way messages should be correlated.

The motivation for this discussion is that the technology stack we’re currently using in one of my projects — a JBI container — quite directly maps WSDL 2.0 MEPs to runtime API constructs. If something is a WSDL 1.1 request-response (WSDL 2.0 in-out), the corresponding MessageExchange created at runtime will be an InOut object. This object will be used to send the request. When the JBI container receives an incoming response — even asynchronously, e.g. when using JMS or WS-A-based async HTTP messaging — it expects the InOut exchange which was used to send the request to be still alive. If it isn’t, it’ll view this as an error. But when something such as RAMP is used, the response might arrive not only minutes, but even days after the request has been sent.

We’re still trying to come up with a solution that seems natural enough for the poor person tasked with designing the WSDL, does not require us to implement lots of message-correlating infrastructure on top of JBI, and doesn’t seem like we’re abusing the technology … maybe what we need is a new WSDL 2.0 MEP (robust-in-robust-out ?)

On September 7, 2005 5:44 AM, Jim Webber said:

You should use SSDL. These ridiculous WSDL 2.0 artefacts don’t exist when you consider the problem in terms of abitrary message exchange rather than some pre-canned silliness.

Jim

On September 7, 2005 6:41 AM, Stefan Tilkov said:

Granted, request/response is just one of many useful patterns - such as request/response/response or subscribe/notify. It’s the most common, though, and one everybody expects to be supported.

I’m inclined to believe SSDL is superior in this regard; it’s not an option though for many reasons, most of them political.

On September 7, 2005 1:17 PM, Jacek said:

Hi Stefan, there are a few points in reply:

1) extensions and bindings in WSDL 2 are basically free to map in-out to asynchronous exchange. I believe it is expected that WS-Addressing WSDL binding will provide such an extension and change the current WSDL HTTP binding to support asynchrony through two HTTP requests for the messages. It might make sense to allow robust-request-response MEP in this case.

2) the robust-request-response MEP allows you to send fault as a reaction to the response, and it is in effect robust-request-robust-response. The robustness here is about being able to fault on normal messages, not about any kinds of synchrony.

3) As for long-running vs. short-running asynchrony, that is an orthogonal decision here. In WASP we had two kinds of async that could be combined (this is info from when I was working on it two years ago, I’m not sure if it changed):

a) server-side/transport asynchrony - receiving the message over one transport channel and sending response back over a different channel. This is useful both for timeout issues (you can’t keep one channel open long enough) and networking issues (you plain don’t have a back channel, like in email transport).

b) client-side asynchrony - instead of modeling the request/response operation as simple Java call, it would be modeled with a callback/polling interface. This is useful for when the client-side processing model makes more sense asynchronously. This can be combined freely with synchronous or asynchronous transport:

  • a short-term asynchronous transport with synchronous client call - for example a quick email exchange in absence of HTTP.

  • a synchronous transport with async client call - the client doesn’t care that the result is there in seconds, it can still do something useful in between.

  • a long-term async transport handled by async client call - normal async operation

  • a synchronous transport and synchronous client call - the well-known default behavior. 8-)

We might invent an extension marker for WSDL that would say “this operation will run long”, indicating that the client might choose an async calling model for this request/response op, and that the server might choose an async binding because otherwise it would run into timeouts. I don’t know of anybody working on such an extension.

I hope this makes sense, the input box is awfully small. 8-)

Jacek

On September 8, 2005 9:58 AM, enric jaen said:

You said: “Everybody and their mother agrees that doing web services RPC-style is a Bad Thing™”

Please, could you explain a bit more why do you say RPC is a bad thing? Do you refer rpc/enc? If the problem is the encoding, you can use the wrapped style [1]

Regarding the asynchronous pattern, I think that the way to correlate two one-way messages is using the wsa:messageId and wsa:relatesTo. (This is something SSDL leaves unclear)

I have a question, do you consider that DOC-style is a resemble of the MOM-paradigm? According to [2] I think so..

[1] http://www-128.ibm.com/developerworks/websphere/library/techarticles/0505flurry/0505flurry.html

[2] http://java.sun.com/developer/technicalArticles/xml/jaxrpcpatterns/#1

-Enric

On September 8, 2005 10:51 AM, Stefan Tilkov said:

Hi Enric,

As to your first question, see this discussion: /blog/st/2005/05/18/rpcstylewebservices.html

You are of course right with regards to wsa:ReplyTo/wsa:MessageID/wsa:RelatesTo, but my point is that there is no accepted way to describe this in WSDL.

On September 8, 2005 11:28 AM, Stefan Tilkov said:

Jacek, thanks for the thorough feedback. I’ve made the comment box wider, hope it suits you now :-)

I think we can agree that API-level asynchronicity (which is probably better termed blocking/non-blocking) is completely orthogonal to transport semantics. If bindings can map an in/out to two one-way transport messages, this means that from the WSDL interface perspective, the correct way to describe an in/out (request/response) exchange is to use the in/out MEP instead of explicitly modeling it as one in and one out (or one robust-in’ and one ‘robust-out’) MEPs.

If this is the case, it would be wrong (or at least not in line with the goal of the spec) for an API and programming toolkit to map a WSDL in/out to some message exchange object that will only live as long as the calling process does, without offering any way for a consumer to receive a response message that arrives asynchronously after a restart. So it’s an API problem, not a WSDL or binding problem.

It seems, though, that there’s a difference between the view taken by WSDL 1.1 and WSDL 2 — where in WSDL 2, in/out is a MEP that can be used for long-running + asynchronous, short-running + asynchronous as well as short-running + synchronous invocations, a WSDL 1.1 request/response can only map to a synchronous transport invocation. Which contradicts the RAMP profile …

On September 8, 2005 3:22 PM, Jacek said:

Wow, now it’s big enough. Please do the same change on the preview page. 8-)

As for the difference between WSDL 1.1 view and WSDL 2 view, I thought I read your original article above as saying exactly the opposite from the last comment. 8-)

In the article, you quote WSDL 1.1 explicitly describing the abstractness of the request/response MEP, supported by text from RAMP. Then you quote WSDL 2 and interpret it to say that in-out is only synchronous, which can be changed by extensions, as I commented. Now in your latest comment you say it the other way. What gives? 8-)

As I see it, both WSDL 1.1 and WSDL 2 allow in-out (or request/response) to be mapped to multiple channels, and neither of them actually does so in the standard bindings. We can hope WS-Addressing WG does a good job here and provides a useful extension for WSDL 2; and maybe they will even go as far as porting it to WSDL 1.1.

On September 8, 2005 3:46 PM, Stefan Tilkov said:

Yes, you are right - I managed to confuse myself :-)