8.3. WS-CDLThough WSCI is more famous, the official choreography model blessed by the W3C's Choreography Working Group is WS-CDL, whose latest working draft was released by the W3C in December 2004.[*] WS-CDL is a brand-new XML process contract language that provides a standard way to specify technical contracts that capture (from a global viewpoint) the common observable behavior of autonomous interacting participants. The distinguishing characteristics of WS-CDL are the following:
8.3.1. Overview of WS-CDLThe object model of WS-CDL is shown in Figure 8-4. Figure 8-4. WS-CDL object modelThe major objects in the model are:
8.3.2. WS-CDL ExampleThe definitive WS-CDL example is the exchange between consumer, retailer, and warehouse in the processing of a purchase order. In Example 8-1, a consumer issues a purchase order request to a retailer, who acknowledges it and then forwards it to a warehouse. If the warehouse accepts the request, the retailer indicates success to the consumer; when the warehouse ships the order, it sends a notification of shipment directly to the consumer. If the warehouse rejects the request, the retailer sends an error to the consumer. Example 8-1. WS-CDL example code1 <?xml version="1.0" encoding="UTF-8"?> 2 <package name="PO" version="1.0" 3 targetNamespace="http://mike.com/cdlpo" 4 xmlns:pons="http://mike.com/cdlpo/types" 5 xmlns:cns="http://mike.com/cdlpo/Consumer" 6 xmlns:rns="http://mike.com/cdlpo/Retailer" 7 xmlns:xsd="http://www.w3.org/2001/XMLSchema" 8 xmlns:tns="http://mike.com/cdlpo/cdlpo" 9 xmlns="http://www.w3.org/2004/12/ws-chor/cdl" 10 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 11 xsi:schemaLocation="http://www.w3.org/2004/12/ws-chor/cdl"> 12 13 <!-- information types (i.e., message data) 14 1. Four PO message types (PO, POAck, POResponse, POShipNotice), 15 2. Basic types: bool, intType, uriType --> 16 <informationType name="PO" type="pons:POMsg"/> 17 <informationType name="POAck" type="pons:POAckMsg"/> 18 <informationType name="POResponse" type="pons:POResponseMsg"/> 19 <informationType name="POShipNotice" type="pons:POShipNotice"/> 20 <informationType name="bool" type="xsd:boolean"/> 21 <informationType name="intType" type="xsd:int"/> 22 <informationType name="uriType" type="xsd:anyURI"/> 23 24 <!-- tokens (i.e., data used in the choreography with locators that use 25 XPath to extract token from an information type) include POID plus 26 references to each of the channels. --> 27 <token name="POID" informationType="tns:intType"/> 28 <token name="retailerRef" informationType="tns:uriType"/> 29 <token name="consumerRef" informationType="tns:uriType"/> 30 <token name="warehouseRef" informationType="tns:uriType"/> 31 <tokenLocator tokenName="tns:POID" informationType="tns:PO" query="orderId"/> 32 <tokenLocator tokenName="tns:POID" informationType="tns:POAck" query="orderId"/> 33 <tokenLocator tokenName="tns:POID" informationType="tns:POResponse" 34 query="orderId"/> 35 <tokenLocator tokenName="tns:POID" informationType="tns:POShipNotice" 36 query="orderId"/> 37 38 <!-- Three roles: consumer, warehouse, and retailer. 39 A role consists of a set of behaviors, 40 each of which represents an web service interface/port type. 41 42 Three relationships: C to R, R to W, C to W. 43 A relationship is a set of cooperating roles. 44 45 Three channels: one for consumer, one for WH, one for retailer. 46 --> 47 <roleType name="Consumer"> 48 <behavior name="c4r" interface="cns:CRPT"/> 49 <behavior name="c4w" interface="cns:CWPT"/> 50 </roleType> 51 <roleType name="Retailer"> 52 <behavior name="r4c" interface="rns:RCPT"/> 53 <behavior name="r4w" interface="rns:RWPT"/> 54 </roleType> 55 <roleType name="Warehouse"> 56 <behavior name="w4r" interface="wns:WPT"/> 57 <behavior name="w4c" interface="wns:WCT"/> 58 </roleType> 59 <relationshipType name="CRRelationship"> 60 <role type="tns:Consumer" behavior="c4r"/> 61 <role type="tns:Retailer" behavior="r4c"/> 62 </relationshipType> 63 <relationshipType name="RWRelationship"> 64 <role type="tns:Retailer" behavior="r4w"/> 65 <role type="tns:Warehouse" behavior="w4r"/> 66 </relationshipType> 67 <relationshipType name="CWRelationship"> 68 <role type="Consumer" behavior="c4w"/> 69 <role type="Warehouse" behavior="w4c"/> 70 </relationshipType> 71 <channelType name="RetailerChannel"> 72 <role type="tns:Retailer" behavior="r4c"/> 73 <reference> <token name="tns:retailerRef"/> </reference> 74 <identity> <token name="tns:POID"/> </identity> 75 </channelType> 76 <channelType name="ConsumerChannel"> 77 <role type="tns:Consumer"/> 78 <reference> <token name="tns:consumerRef"/> </reference> 79 <identity> <token name="tns:POID"/> </identity> 80 </channelType> 81 <channelType name="WarehouseChannel"> 82 <role type="tns:Warehouse"/> 83 <reference> <token name="tns:warehouseRef"/> </reference> 84 <identity> <token name="tns:POID"/> </identity> 85 </channelType> 86 87 <!-- RWChoreo models the interaction between retailer and 88 warehouse. Retailer calls Warehouse handlePO operation, 89 passing a PO and getting back a Boolean (success or failure). 90 Retailer also passes consumer's channel to warehouse. 91 Sets consumerSatisfied = true/false on exit. --> 92 <choreography name="RWChoreo"> 93 <relationship type="tns:RWRelationship"/> 94 <variableDefinitions> 95 <!-- this variable is the output of the choreo --> 96 <variable name="consumerSatisfied" informationType="tns:bool" 97 roleTypes="tns:Retailer" free="true"/> 98 99 <!-- messages of WS call: poR/poW is sent from R to W 100 okW/ok is sent back from W to R. --> 101 <variable name="poR" informationType="tns:PO" 102 roleTypes="tns:Retailer" free="true"/> 103 <variable name="poW" informationType="tns:PO" 104 roleTypes="tns:Warehouse" free="true"/> 105 <variable name="okW" 106 informationType="tns:bool" roleTypes="tns:Warehouse"/> 107 <variable name="okR" 108 informationType="tns:bool" roleTypes="tns:Retailer"/> 109 110 <!-- The two channels used in this choreo. WChannel is the 111 endpoint of the service. CChannel is passed to it 112 for a future notifcation from W to C --> 113 <variable name="WChannel" channelType="tns:WarehouseChannel"/> 114 <variable name="CChannel" channelType="tns:ConsumerChannel"/> 115 </variableDefinitions> 116 <sequence> 117 <interaction name="RWInteraction" channelVariable="tns:WChannel" 118 operation="handlePO"> 119 <participate relationshipType="tns:RWRelationship" 120 fromRole="tns:Retailer" toRole="tns:Warehouse"/> 121 <exchange name="RWReq" informationType="tns:PO" action="request"> 122 <senmud variable="cdl:getVariable(poR,tns:Retailer)"/> 123 <receive variable="cdl:getVariable(poW,tns:Warehouse)"/> 124 </exchange> 125 <exchange name="RWRsp" informationType="tns:bool" action="respond"> 126 <send variable="cdl:getVariable(okW, tns:Warehouse)"/> 127 <receive variable="cdl:getVariable(okR, tns:Retailer)"/> 128 </exchange> 129 <record name="CChannelRecord" when="before"> 130 <source variable="cdl:getVariable(poW, channel, tns:Warehouse)"/> 131 <target variable="cdl:getVariable(CChannel, tns:Warehouse)"/> 132 </record> 133 </interaction> 134 <!-- set variable consumerSatisfied with the result. --> 135 <assign roleType="tns:Retailer"> 136 <copy name="popSat"> 137 <source variable="boolean(cdl:getVariable(poR, 138 Response, tns:Retailer))"/> 139 <target variable="cdl:getVariable(consumerSatisfied, 140 tns:Retailer)"/> 141 </copy> 142 </assign> 143 </sequence> 144 </choreography> 145 146 <!-- CWChoreo models the consumer-warehouse relationship. Warehouse 147 sends consumer a ship notice. --> 148 <choreography name="CWChoreo"> 149 <relationship type="tns:CWRelationship"/> 150 <variableDefinitions> 151 <variable name="noticeW" 152 informationType="tns:POShipNotice" roleTypes="tns:Warehouse"/> 153 <variable name="noticeC" 154 informationType="tns:POShipNotice" roleTypes="tns:Consumer"/> 155 <variable name="CChannel" 156 channelType="tns:ConsumerChannel" roleTypes="tns:Warehouse" 157 free="true"/> 158 </variableDefinitions> 159 <interaction name="POShipNoticeInteraction" 160 channelVariable="tns:CChannel" operation="handlePOShipNotice"> 161 <participate relationshipType="tns:CWRelationship" 162 fromRole="tns:Warehouse" toRole="tns:Consumer"/> 163 <exchange name="CWSend" 164 informationType="tns:POShipNotice" action="request"> 165 <send variable="cdl:getVariable(noticeW, tns:Warehouse)"/> 166 <receive variable="cdl:getVariable(noticeC, tns:Consumer)"/> 167 </exchange> 168 </interaction> 169 </choreography> 170 171 <!-- PO is the main choreo modeling the overall exchange. It 172 performs the two choreos above. 173 1. The consumer-retailer interaction: consumer sends PO to retailer. 174 2. Perform the retailer-warehouse interaction. 175 3. If 2 is ok, retailer sends consumer a response, and then we 176 perform the warehouse-consumer interaction. 177 4. Else, retailer sends consumer an error. --> 178 <choreography name="PO" root="true"> 179 <relationship type="tns:CRRelationship"/> 180 <relationship type="tns:RWRelationship"/> 181 <relationship type="tns:CRRelationship"/> 182 <variableDefinitions> 183 <!-- message types used in the choreo --> 184 <variable name="poC" informationType="tns:PO" 185 roleTypes="tns:Consumer"/> 186 <variable name="poW" informationType="tns:PO" 187 roleTypes="tns:Warehouse"/> 188 <variable name="poR" informationType="tns:PO" 189 roleTypes="tns:Retailer"/> 190 <variable name="poAckC" informationType="tns:POAck" 191 roleTypes="tns:Consumer"/> 192 <variable name="poAckR" informationType="tns:POAck" 193 roleTypes="tns:Retailer"/> 194 <variable name="poPosRespR" informationType="tns:POResponse" 195 roleTypes="tns:Retailer"/> 196 <variable name="poNegRespR" informationType="tns:POResponse" 197 roleTypes="tns:Retailer"/> 198 <variable name="poRespC" informationType="tns:POResponse" 199 roleTypes="tns:Consumer"/> 200 201 <!-- boolean output of warehouse drives choice logic below --> 202 <variable name="internalResponse" informationType="tns:bool" 203 roleTypes="tns:Retailer"/> 204 205 <!-- retailer and consumer channels used in the choreo --> 206 <variable name="RChannel" channelType="tns:RetailerChannel"/> 207 <variable name="CChannel" channelType="tns:ConsumerChannel"/> 208 </variableDefinitions> 209 210 <sequence> 211 <!-- interaction: consumer sends retailer a PO.--> 212 <interaction name="POInteraction" channelVariable="tns:RChannel" 213 operation="handlePO" initiate="true"> 214 <participate relationshipType="tns:CRRelationship" 215 fromRole="tns:Consumer" toRole="tns:Retailer"/> 216 <exchange name="POReq" informationType="tns:PO" action="request"> 217 <send variable="cdl:getVariable(poC, tns:Consumer)"/> 218 <receive variable="cdl:getVariable(poR, tns:Retailer)"/> 219 </exchange> 220 <exchange name="PORsp" informationType="tns:POAck" action="respond"> 221 <send variable="cdl:getVariable(poAckR, tns:Retailer)"/> 222 <receive variable="cdl:getVariable(poAckC, tns:Consumer)"/> 223 </exchange> 224 <record name="CustomerChannelRecord" when="before"> 225 <source variable="cdl:getVariable(poR, 226 PO/CustomerRef, tns:Retailer)"/> 227 <target variable="cdl:getVariable(CChannel, tns:Retailer)"/> 228 </record> 229 </interaction> 230 231 <!-- perform the RW choreo: pass in poR, save output in variables 232 poW and internalResponse --> 233 <perform choreographyName="tns:RWChoreo"> 234 <bind name="n1"> 235 <this variable="cdl:getVariable(poR, tns:Retailer)" 236 role="tns:Retailer"/> 237 <free variable="cdl:getVariable(poR, rwns:Retailer)" 238 role="rwns:Retailer"/> 239 </bind> 240 <bind name="n2"> 241 <this variable="cdl:getVariable(poW, tns:Warehouse)" 242 role="tns:Warehouse"/> 243 <free variable="cdl:getVariable(poW, tns:Warehouse)" 244 role="tns:Warehouse"/> 245 </bind> 246 <bind name="n3"> 247 <this variable="cdl:getVariable(internalResponse,tns:Retailer)" 248 role="tns:Retailer"/> 249 <free variable="cdl:getVariable(consumerSatisfied, tns:Retailer)" 250 role="rwns:Retailer"/> 251 </bind> 252 </perform> 253 254 <choice> 255 <!-- if warehouse responded postively, retailer sends positive 256 response to consumer, and performs the CW choreography 257 so warehouse can send notice to consumer --> 258 <workunit name="positivePOResponse" 259 guard="boolean(internalResponse)" block="false"> 260 <sequence> 261 <interaction name="POResponseInteraction" 262 channelVariable="tns:CChannel"operation="handlePOResponse"> 263 <participate relationshipType="tns:CRRelationship" 264 fromRole="tns:Retailer" toRole="tns:Consumer"/> 265 <exchange name="n1" informationType="tns:POResponse" 266 action="request"> 267 <send variable="cdl:getVariable(poPosRespR, 268 tns:Retailer)"/> 269 <receive variable="cdl:getVariable(poRespC,tns:Consumer)"/> 270 </exchange> 271 </interaction> 272 <perform choreographyName="tns:CWChoreo"> 273 <bind name="n1"> 274 <this variable="cdl:getVariable(CChannel, rwns:Warehouse)" 275 role="rwns:Warehouse"/> 276 <free variable="cdl:getVariable(CChannel, rwns:Warehouse)" 277 role="rwns:Warehouse"/> 278 </bind> 279 </perform> 280 </sequence> 281 </workunit> 282 283 <!-- if warehouse responded negatively, retailer sends negative 284 response to consumer --> 285 <workunit name="negativePOResponse" 286 guard="not(boolean(internalResponse))" block="false"> 287 <interaction name="POResponseInteraction" 288 channelVariable="tns:CChannel" operation="handlePOResponse"> 289 <participate 290 relationshipType="tns:CRRelationship" 291 fromRole="tns:Retailer" toRole="tns:Consumer"/> 292 <exchange name="n1" informationType="tns:POResponse" 293 action="request"> 294 <send variable="cdl:getVariable(poNegRespR, tns:Retailer)"/> 295 <receive variable="cdl:getVariable(poRespC, tns:Consumer)"/> 296 </exchange> 297 </interaction> 298 </workunit> 299 </choice> 300 </sequence> 301 </choreography> 302 </package> The example begins with the declaration of information types (lines 16-22), containing mostly message type declarations (e.g, PO, or purchase order request, in line 16). Tokens are defined in lines 27-36; for example, purchase order ID (POID) on line 27. Lines 47-89 describe the structural composition of roles, relationships, and channels, which is depicted in Figure 8-5. Each of the three roles (represented by large boxes in the figure)Retailer, Warehouse, and Consumerhas its own channel (shown as ovals)RetailerChannel, WarehouseChannel, and ConsumerChannel, respectively. Each role has two web-service-based behaviors, represented by the small inner boxes; for example, the retailer's behaviors are r4c (retailer for consumer) and r4w (retailer for warehouse). The arrows show the types of message exchanges encountered in the choreography. For example, the arrow from r4w to the warehouse channel represents an exchange between the r4w behavior of the retailer and the warehouse; the arrow from the warehouse channel to w4r indicates that the warehouse uses its w4r behavior to process events on its channel. As the figure illustrates, each role has connections to the others, implying that there are three relationships: customer and retailer, consumer and warehouse, and retailer and warehouse. Three choreographies are presented in the code. The first, in lines 92-144, describes the behavior of the retailer-warehouse relationship:
The second choreography, in lines 148-169, captures the warehouse-to-consumer exchange, which occurs on the consumer channel (CChannel in line 160) and involves the sending of a notification from the warehouse's noticeW variable to the consumer's noticeC variable. The third and final choreography (lines 178-301) drives the overall exchange. In the first interaction of this choreography, in 212-229, the consumer sends the purchase order to the retailer (lines 216-219), and the retailer responds with an acknowledgment (lines 220-223). Next comes the perform activity in lines 233-252, in which the choreography invokes the retailer-warehouse choreography, passing in the purchase order the retailer received from the consumer (lines 234-239) and getting back the Boolean result (lines 246-251). The two possible outcomes of this result are treated with a choice activity. The work unit positivePOResponse (lines 258-281) is encountered if the result was true. In this case, the retailer sends a positive response to the consumer (lines 261-271) and the customer-warehouse choreography is performed (lines 272-278). In the false case (lines 285-298), the retailer sends a negative response to the consumer. 8.3.3. Strengths of WS-CDLFrom the previous discussion, you can draw the following conclusions about the general nature of WS-CDL:
8.3.4. The Future of WS-CDLWhatever the merits of its model, WS-CDL faces a tough political fight. Written by Oracle, but having no support from Microsoft or IBM (an ominous sign), WS-CDL inevitably will need to justify its existence in a BPEL-dominated world. The decision for customers need not be an either/or: WS-CDL and BPEL are complementary and can coexist in a real-world BPM architecture (in fact, WS-CDL is recommended for the architecture presented in Chapter 2), but only if vendors build good WS-CDL implementations and customers buy them. WS-CDL is young; it is too soon to tell. |