- From: Williams, Stuart <skw@hplb.hpl.hp.com>
- Date: Tue, 3 Jul 2001 15:25:36 +0100
- To: "'xml-dist-app@w3.org'" <xml-dist-app@w3.org>
Attached below are some thoughts on protocol bindings largely derived from material in Section 5 of the Abstract Model [6] and discussions with Marc Hadley and John Ibbotson. Thoughts and comments welcome. Best Regards Stuart Williams -- XMLP Bindings ------------- The purpose of an XML Protocol Binding is to provide rules for the transfer of XML Protocol messages over some specific underlying protocol. The purpose of a binding architecture is to provide an abstraction so that the core of the XML protocol can be defined(specified) independently from the definition (specification) of particular protocol bindings. +---------------------------------------+ | Core XML Protocol | +---------------------------------------+ ---------------------------------------- Binding Interface +aaaaaaaaa+ +aaaaaaaaa+ +aaaaaaaaa+ | Nestable| | P2 | | Pn | | Binding | | Binding |......| Binding | |aaaaaaaaa+ | | | | | P1 | +yyyyyyyyy+ | | | Binding | | P2 | +zzzzzzzzz+ +xxxxxxxxx+ +---------+ | Pn | | P1 | +---------+ +---------+ Fig. 1 Outline Binding Architecture. Fig. 1 above is based on [1]. The different letter codings at the boundaries beneath the Binding Interface ("aaaaa") are intended to acknowledge that each protocol binding, P1, P2,..., Pn is in general specific to that particular underlying protocol, or more particularly to the services provided by the underlying protocol. Thus, the P1 binding is specific to the services of the P1 protocol and so on. Figure 1 illustrates a single nestable binding that both provides the binding interface ("aaaa...") at its upper boundary and use the binding interface at its lower boundary to bind to a protocol binding, P1-Pn, or to a further nestable binding(s) between itself and an underlying protocol binding. The key architectural interface then is the Binding Interface, "aaaaaaaa". Protocol bindings define convergence or adaption functions that adapt the behaviour (or services) provided by underlying protocols into the behaviour (or services) of the Binding Interface. Nestable Bindings act as 'shims' that are interposed between the top of a protocol binding and the core XML protocol. NB: This proposal makes the assumption that the purpose of a binding is to create a common abstraction across all underlying protocol that 'hides' the functional differences between different underlying protocols. This common abstraction is characterised in the definition of a single (abstract) Binding Interface ("aaaaa..."). This assumption is may not be universally shared! Message Exchange Patterns ------------------------- One of the largest areas for differences in behaviours between underlying protocols is the message exchange patterns that each naturally supports. HTTP [2] naturally supports request/response patterns; SMTP [3] naturally supports a one-way pattern; TCP/IP [4] provides a bi-directional, mutually asynchronous bytestreams; BEEP [5] provides for more conversational message patterns - BEEP sessions and channels provide context for extended exchanges of messages between communicating peers. There are two broad approaches to the definition of an abstract binding interface: 1) The interface provides a framework such that a binding can declare what functionality it supports. Thus not all bindings support all message patterns. Mechanisms to address common shortcommings can be built-up either as (shared? - at least in definition) nestable bindings or defined as part of the core XML protocol. In the worst case an application (a user of the core XML protocol) needs to be able to adapt its behaviour to suit the cumulative capabilities of the nested bindings (if any) and the capabilities of the underlying protocol plus binding. 2) The alternate view is that bindings raise (or reduce) the native functionality of an underlying protocol to meet some common level of functionality across all supported protocols. Core XML protocol and application behaviour is then truely agnostic (from a functional point-of-view) to the capabilities of a particular underlying protocol. Some bindings/protocol combinations may be more efficient in certain regards than others eg. some may directly support the inclusion of binary attachments, some may intrinsically support the notions of session or request/response. Nestable bindings may be added to provide functionality that is missing from the underlying protocol - eg. message correlation, session orientation... or to improved the efficiency of particular functional aspects - eg. a MIME/DIME nestable binding could provide for the more efficient serialisation of arbitrary attachments than say an internal base64 serialisation within the transmitted XML protocol envelope. To provide a Binding Interface abstraction that supports an extensible (and emergent) set of message exchange pattern we of a binding as supporting operations with an explict lifecycle. Operations start, message get exchanged and they end. Drawing on the material in section 5 of the Abstract Model [6]: Operation Livecycle Primitives (at a single binding interface) ------------------------------ Active initiation: Passive initiation: Op.start-req Op.start-ind Op.start-conf Op.start-resp ... ... ... ... Active termination: Passive termination ... ... ... ... Op.end-req Op.end-ind Op.end-conf Op.end-resp NB: This is intended to illustrate the passive and active initiation and termination of an operation at a single node. Time progresses down the page. Message transmission and reception can only occur (within this abstraction) as part of a 'open' (not yet terminated) operation: Sender Receiver Op.start-xxx Op.start-xxx ;xxx=req or ind Op.start-yyy Op.start-yyy ;yyy=conf or resp ... ... Op.msg-send Op.msg-recv ;Message transfer ... ... Op.end-xxx Op.end-xxx Op.end-yyy Op.end-yyy NB. the only temporal constraint implied here between sender and receiver is that Op.msg-recv occurs after the corresponding Op.msg-send. Operation Lifecycle and Messaging primitives -------------------------------------------- [This is just a 'sketch'] Active initiation: ------------------ Op.start-req(PeerURI, MessagePattern, LocalBindingContext) Op.start-conf(Status, LocalBindingContext) Passive initiation ------------------ Op.start-ind(PeerURI, MessagePattern, LocalBindingContext) Op.start-resp(Status, LocalBindingContext) Active termination ------------------ Op.end-req(Reason, LocalBindingContext) Op.end-conf(Status, LocalBindingContext) Passive termination ------------------- Op.end-ind(Reason, LocalBindingContext) Op.end-resp(Status, LocalBindingContext) Message Transmission -------------------- Op.msg-send(Wrapper, Envelope, Attachments, LocalCausality, Sequence, LocalBindingContext) Message Reception ----------------- Op.msg-recv(Wrapper, Envelope, Attachments, LocalCausality, Sequence, LocalBindingContext) NB: May have been too liberal with inclusion of LocalBindingContext. BindingContext carries through from AM section 3. NB: On causality... as a starting point the thinking here is that discussed in [7] and subsequent discussions. We may substituted the notion of a global message reference rather than a local message reference. I would expect the temporal scoping of a local message reference to be bounded by the lifetime of the corresponding operation - ie. between Op.start-??? and Op.end-??? NB: It would be nice not to have to explicitly communicate a value for MessagePattern. For HTTP on could imagine using HTTP PUT to do a pure one-way message from HTTP client to HTTP server. One-way and request-response are both degenerate cases of request-multiresponse with zero and one responses respectively. For conversational/session oriented messages, LocalCausality threads the conversation at each local end. NB: Bindings may augment the content of an envelope with additional headers to enable non-native MEP's. Example Message Exchange Patterns: ---------------------------------- One-Way: Sender: Op.start-req(PeerURI="destURI", MessagePattern="one-way", LocalBindingContext="sCtx1"); Op.start-conf(Status="ok", LocalBindingContext="sCtx2"); Op.msg-send(Envelope="envelope1", Attachments="attachments1", LocalCausality="null", Sequence="0", LocalBindingContext="sCtx3"); Op.end-req(Reason="normal", LocalBindingContext="sCtx4"); Op.end-conf(Status="ok" LocalBindingContext="sCtx5"); Receiver: Op.start-ind(PeerURI="fromURI", MessagePattern="one-way", LocalBindingContext="rCtx1"); Op.start-resp(Status="ok", LocalBindingContext="rCtx2"); Op.msg.recv(Envelope="envelope1", Attachments="attachments1", LocalCausality="null", Sequence="0", LocalbindingContext="rCtx3"); Op.end-ind(Reason="normal", LocalBindingContext="rCtx4"); Op.end-resp(Status="ok", LocalBindingContext="rCtx5"); Request-Response: Sender: Op.start-req(PeerURI="destURI", MessagePattern="request-response", LocalBindingContext="sCtx1"); Op.start-conf(Status="ok", LocalBindingContext="sCtx2"); Op.msg-send(Envelope="envelope1", Attachments="attachments1", LocalCausality="null", Sequence="0", LocalBindingContext="sCtx3"); Op.msg-recv(Envelope="envelope2", Attachments="attachments2", LocalCausality="&envelope1", Sequence="0", LocalBindingContext="sCtx4"); Op.end-req(Reason="normal", LocalBindingContext="sCtx5"); Op.end-conf(Status="ok" LocalBindingContext="sCtx6"); Receiver: Op.start-ind(PeerURI="fromURI", MessagePattern="request-response", LocalBindingContext="rCtx1"); Op.start-resp(Status="ok", LocalBindingContext="rCtx2"); Op.msg-recv(Envelope="envelope1", Attachments="attachments1", LocalCausality="null", Sequence="0", LocalbindingContext="rCtx3"); Op.msg-send(Envelope="envelope2", Attachments="attachments2", LocalCausality="&envelope1", Sequence="0", LocalBindingContext="rCtx4"); Op.end-ind(Reason="normal", LocalBindingContext="rCtx5"); Op.end-resp(Status="ok", LocalBindingContext="rCtx6"); Request-Multiresponse: Sender: (Note Passive termination) Op.start-req(PeerURI="destURI", MessagePattern="request-response", LocalBindingContext="sCtx1"); Op.start-conf(Status="ok", LocalBindingContext="sCtx2"); Op.msg-send(Envelope="envelope1", Attachments="attachments1", LocalCausality="null", Sequence="0", LocalBindingContext="sCtx3"); Op.msg-recv(Envelope="envelope2", Attachments="attachments2", LocalCausality="&envelope1", Sequence="0", LocalBindingContext="sCtx4"); Op.msg-recv(Envelope="envelope3", Attachments="attachments3", LocalCausality="&envelope1", Sequence="1", LocalBindingContext="sCtx5"); Op.msg-recv(Envelope="envelope4", Attachments="attachments4", LocalCausality="&envelope1", Sequence="2", LocalBindingContext="sCtx6"); ... ... Op.msg-recv(Envelope="envelopeN", Attachments="attachmentsN", LocalCausality="&envelope1", Sequence="N-1", LocalBindingContext="sCtx7"); Op.end-ind(Reason="normal", LocalBindingContext="sCtx8"); Op.end-resp(Status="ok" LocalBindingContext="sCtx9"); Receiver: (Note active termination) Op.start-ind(PeerURI="fromURI", MessagePattern="request-response", LocalBindingContext="rCtx1"); Op.start-resp(Status="ok", LocalBindingContext="rCtx2"); Op.msg-recv(Envelope="envelope1", Attachments="attachments1", LocalCausality="null", Sequence="0", LocalbindingContext="rCtx3"); Op.msg-send(Envelope="envelope2", Attachments="attachments2", LocalCausality="&envelope1", Sequence="0", LocalBindingContext="rCtx4"); Op.msg-send(Envelope="envelope3", Attachments="attachments3", LocalCausality="&envelope1", Sequence="1", LocalBindingContext="rCtx5"); Op.msg-send(Envelope="envelope4", Attachments="attachments4", LocalCausality="&envelope1", Sequence="2", LocalBindingContext="rCtx6"); ... ... Op.msg-send(Envelope="envelopeN", Attachments="attachmentsN", LocalCausality="&envelope1", Sequence="N-2", LocalBindingContext="rCtx7"); Op.end-req(Reason="normal", LocalBindingContext="rCtx8"); Op.end-conf(Status="ok", LocalBindingContext="rCtx9"); Example HTTP Binding and Request/Response MEP --------------------------------------------- HTTP Request/Response via HTTP Post: Sender: Op.start-req(PeerURI="destURI", MessagePattern="request-response", LocalBindingContext="sCtx1"); Op.start-conf(Status="ok", LocalBindingContext="sCtx2"); Op.msg-send(Envelope="envelope1", Attachments="attachments1", LocalCausality="null", Sequence="0", LocalBindingContext="sCtx3"); POST "destURI" HTTP/1.1 Content-Type: text/xml Content-Length: NNNN SOAP-Action: <SoapActionURI from BindingCtx> <Env:Envelope ...> <Env:Headers> <!-- headers from "envelope1"--> ... </Env:Headers> <Env:Body> <!-- bodies from "envelope1"--> ... </Env:Body> <Env:Attachments> <!-- attachments from "attachment1" --> <Env:Attachment id="Att1" xsi:type="base64"> ... </Env:Attachment> <Env:Attachment id="Att2" xsi:type="base64"> ... </Env:Attachment> </Env:Attachments> </Env:Envelope> HTTP/1.1 200 OK Content-Type: text/xml Content-Length: NNNN <Env:Envelope ...> <Env:Headers> <!-- headers from "envelope2"--> ... </Env:Headers> <Env:Body> <!-- bodies from "envelope2"--> ... </Env:Body> <Env:Attachments> <!-- attachments from "attachment2" --> <Env:Attachment id="Att1" xsi:type="base64"> ... </Env:Attachment> <Env:Attachment id="Att2" xsi:type="base64"> ... </Env:Attachment> </Env:Attachments> </Env:Envelope> Op.msg-recv(Envelope="envelope2", Attachments="attachments2", LocalCausality="&envelope1", Sequence="0", LocalBindingContext="sCtx4"); Op.end-req(Reason="normal", LocalBindingContext="sCtx5"); Op.end-conf(Status="ok" LocalBindingContext="sCtx6"); Receiver: Op.start-ind(PeerURI="fromURI", MessagePattern="request-response", LocalBindingContext="rCtx1"); Op.start-resp(Status="ok", LocalBindingContext="rCtx2"); POST "destURI" HTTP/1.1 Content-Type: text/xml Content-Length: NNNN SOAP-Action: <SoapActionURI from BindingCtx> <Env:Envelope ...> <Env:Headers> <!-- headers from "envelope1"--> ... </Env:Headers> <Env:Body> <!-- bodies from "envelope1"--> ... </Env:Body> <Env:Attachments> <!-- attachments from "attachment1" --> <Env:Attachment id="Att1" xsi:type="base64"> ... </Env:Attachment> <Env:Attachment id="Att2" xsi:type="base64"> ... </Env:Attachment> </Env:Attachments> </Env:Envelope> Op.msg-recv(Envelope="envelope1", Attachments="attachments1", LocalCausality="null", Sequence="0", LocalbindingContext="rCtx3"); Op.msg-send(Envelope="envelope2", Attachments="attachments2", LocalCausality="&envelope1", Sequence="0", LocalBindingContext="rCtx4"); HTTP/1.1 200 OK Content-Type: text/xml Content-Length: NNNN <Env:Envelope ...> <Env:Headers> <!-- headers from "envelope2"--> ... </Env:Headers> <Env:Body> <!-- bodies from "envelope2"--> ... </Env:Body> <Env:Attachments> <!-- attachments from "attachment2" --> <Env:Attachment id="Att1" xsi:type="base64"> ... </Env:Attachment> <Env:Attachment id="Att2" xsi:type="base64"> ... </Env:Attachment> </Env:Attachments> </Env:Envelope> Op.end-ind(Reason="normal", LocalBindingContext="rCtx5"); Op.end-resp(Status="ok", LocalBindingContext="rCtx6"); [1] http://www.w3.org/2000/xp/Group/1/04/23/XMLProtocolAbstractModel.html#Fig5.1 [2] http://www.ietf.org/rfc/rfc2616.txt [3] http://www.ietf.org/rfc/rfc2821.txt [4] http://www.ietf.org/rfc/rfc0793.txt [5] http://www.ietf.org/rfc/rfc3080.txt [6] http://www.w3.org/2000/xp/Group/1/04/23/XMLProtocolAbstractModel.html#Sec5 [7] http://lists.w3.org/Archives/Public/xml-dist-app/2001Mar/0216.html
Received on Tuesday, 3 July 2001 10:25:44 UTC