Coordinated Choreographies Proposal 6 - Extending Choreographies

Coordinated Choreographies WS-CDL Spec Changes
Plain text inline, pdf to come Monday, word.doc sent on request.

Extending Choreographies

The extends mechanism provides a kind of inheritance relationship from
parent CDL elements to child CDL elements.

The result is a merger of the behaviors of both parent and child
packages and/or choreographies.

The benefits of this mechanism include:
*	providing standard interaction patterns to be emulated by child
choreographies, as in industry business protocol standards;
*	providing patterns for coordination/transaction protocols;
*	providing a mechanism for tool support for choreography
patterns.

The extends mechanism only allows single inheritance, that is, a child
choreography can extend one and only one parent choreography.  However,
one parent choreograph may be extended by many child choreographies.

Any CDL element with a name may be extended by a compatible child
element.  That includes: a Package as a whole, Role Types, Participant
Types, Channel Types, Relationship Types, Information Types, a
Choreography as a whole, Variables, Tokens, Work Units, Interactions,
Exchanges, Records, Exception Blocks and Finalizer Blocks.

With one exception, the syntax is very simple: the second statement of
the child element which is to extend a parent element must take the
form:
   <extends name=ncname/>
where ncname is the name of the parent element to be extended, which
must be of the same type as the child element.

The exception is Packages, where the syntax is:
   <extends name=<uri>/>

[Part of this proposal is to add an optional extends element to each of
the CDL elements listed above. Alternatively, extends could be an
attribute. ]

Extends for inner elements of a choreography can only be used inside a
choreography which is itself extended.

This mechanism imposes some constraints on parent elements: 
*	A parent element to be extended must have a name.
*	If a parent choreography performs another choreography, the
performed choreography must be enclosed within the parent choreography.
The parent choreography cannot perform another choreography that is
outside its scope.
o	However, a choreography designer would be well advised to keep
parent choreographies simple.  Performing even enclosed choreographies
makes the parent-child relationship much more complex.

Notably excluded from being extended are Ordering Structures, which do
not have names.  The Ordering Structures of the parent choreography must
be reproduced exactly in the child choreography.

Other than for elements of Ordering Structures, "merger of behaviors"
means that any elements of the parent choreography that are not extended
by the child, still occur in the merged choreography. For these
unextended elements to work properly in the merged choreography, the
child choreography may need to extend (alias) the roles and variables
involved. It also means that the child choreography has no mechanism to
turn off or override parent behaviors.  [Should we add one?]

"Merger of behaviors" also means that the child may add additional
behaviors that are not present in the parent, and they will also occur
in the merged choreography.  

Extending an element usually amounts to mapping names of child elements
to parent elements, e.g. mapping role and variables names from something
abstract (for example, a protocol role like "Superior") to something
concrete (for example, a business role like "CreditRequestor"). 

In all cases, extending an element does not change any of its attributes
except for those whose values have already been extended by the same
child.   For example, in an Interaction, channels, relationships, roles,
etc. might be overridden by child-extended versions of the elements
specified in the parent. 

It is invalid for the child to override with a value that was not
extended from the element specified in the parent element.  For example,
if the parent element specified a roleType, the extended child element
must specify a roleType that was extended from the same roleType as in
the parent element.  It is also invalid for the child to change a simple
value that cannot be extended, e.g. causeException="true". 

However, the child may add more Work Units to extended Choreographies
and more activities to Work Units, and may add additional respond
Exchanges and Records with causeException="true" to Interactions.  

In every case where a child adds elements that are not extended from
parent elements, the child elements are added in at the end of the
parent elements in the directly enclosing extended CDL construct, and
are to be executed in sequence after the parent elements.  For example,
if the child adds activities to an extended Work Unit, the additional
activities are added after the last parent activity in the extended Work
Unit.

In the case of coordination protocols, it may not be necessary to define
every aspect of the protocol in the parent choreography.  For example,
the parent choreography below can be bound to a variety of business
transaction protocols, but the underlying protocols have more signals
than are shown in the choreography.  It may only be useful to put
interactions that might have business content into the choreography,
while the lower-level protocol signals are handled by transaction
infrastructure software.

Moreover, while bindings to coordination and other underlying protocols
are not specified by WS-CDL, we assume that they will be required in
many situations (see the explanation of the Choreography coordination
attribute in Section ? and the discussion about Coordination/Transaction
Protocols in Section 6).  In such situations, the protocol needs only to
be bound once for the parent choreography, to be inherited by the
children.
 
Example

This example shows a coordinated parent Choreography modelling a generic
business transaction protocol, extended by a Credit Authorization
Choreography that follows the protocol.

[The example uses Nick's exception-throwing proposal. The
exception-throwing mechanism does not affect the Extends proposal.]

   <roleType name="Superior">
      <behavior name="superiorForInferior"/>
   </roleType>
   <roleType name="Inferior">
      <behavior name="inferiorForSuperior"/>
   </roleType>
   <relationshipType name="SuperiorInferior">
      <role type="tns:Superior" behavior="superiorForInferior"/>
      <role type="tns:Inferior" behavior="inferiorForSuperior"/>
   </relationshipType>
   <informationType name="refusalType" exceptionType="true"/>
   
   <!-- Extensions -->
   <roleType name="CreditRequestor">
      <extends name="Superior"/>
      <behavior name="requestCredit">
         <extends name="superiorForInferior"/>
      </behavior>
   </roleType>
   <roleType name="CreditResponder">
      <extends name="Inferior"/>
      <behavior name="extendCredit">
         <extends name="inferiorForSuperior"/>
      </behavior>
   </roleType>
   <relationshipType name="CreditReqCreditResp">
      <extends name="SuperiorInferior"/>
   </relationshipType>   
   <informationType name="creditDeniedType">
      <extends name="refusalType"/>
   </informationType>
   
   <!-- Parent Coordination choreography with new exceptions-->
   <choreography name="Coordination" root="false" coordinated="true">
      <relationship type="tns:SuperiorInferior"/>
      <variableDefinition>
         <variable name="state" silentAction="true"/>
         <variable name="requestAndContext"/>
         <variable name="positiveResponse"/>
         <variable name="refusal" informationType="tns:refusalType"/>
      </variableDefinition>
      
      <!-- the normal work - receive the request and decide whether to
approve -->
      <interaction name="activePhase" channelVariable="tns:coordination"
operation="propagate">
         <participate relationship="SuperiorInferior"
fromRole="tns:Superior" toRole="Inferior"/>
         <exchange name="propagate" informationType="requestAndContext"
action="request">
            <send variable="tns:requestAndContext"/>
            <receive variable="tns:requestAndContext"/>
         </exchange>
         <exchange name="prepared" informationType="positiveResponse"
action="respond">
            <send variable="tns:positiveResponse"/>
            <receive variable="tns:positiveResponse"/>
         </exchange>
         <exchange name="refused" informationType="refusal"
action="respond">
            <send variable="tns:refusal" causeException="true"/>
            <receive variable="tns:refusal" causeException="true"/>
         </exchange>
      </interaction>
      
      <!-- catch the exception - as an exception it will abort the
choreography and the finalizers are not accessible -->
      <exception name="handleRefusedException">
         <interaction name="refused" channelVariable="tns:coordination"
operation="refused">
            <participate relationship="SuperiorInferior"
fromRole="tns:Inferior" toRole="Superior"/>
         </interaction>
      </exception>
      
      <!-- Finalizers -->
      <!-- what to do if the decision is to confirm -->
      <finalizer name="confirm">
         <interaction name="confirm" channelVariable="tns:coordination"
operation="confirm">
            <participate relationship="SuperiorInferior"
fromRole="tns:Superior" toRole="Inferior"/>
         </interaction>
      </finalizer>
      <!-- what to do if the decision is to cancel -->
      <finalizer name="cancel" default="true">
         <interaction name="cancel" channelVariable="tns:coordination"
operation="cancel">
            <participate relationship="SuperiorInferior"
fromRole="tns:Superior" toRole="Inferior"/>
         </interaction>
      </finalizer>
   </choreography>
   
   <!-- Coordination child CreditAuthorization  choreography -->
   <choreography name="CreditAuthorization" root="false"
coordinated="true">
      <extends name="Coordination"/>
      <relationship type="tns:CreditReqCreditResp"/>
      <variableDefinition>
         <variable name="CreditExtended" informationType="xsd:int"
silentAction="true" roleType="tns:CreditResponder"/>
         <variable name="creditRequest">
            <extends name="requestAndContext"/>
         </variable>
         <variable name="creditAuthorized">
            <extends name="positiveResponse"/>
         </variable>
         <variable name="creditDenied">
            <extends name="refusal"/>
         </variable>
      </variableDefinition>
      
      <!-- the normal work - receive the request and decide whether to
approve -->
      <interaction name="creditAuthorization"
channelVariable="tns:CreditRequestor">
         <extends name="activePhase"/>
         <participate relationship="SuperiorInferior"
fromRole="tns:Superior" toRole="Inferior"/>
         <exchange name="creditRequest"
informationType="creditRequestType" action="request">
            <extends name="propagate"/>
            <send variable="tns:creditRequest"/>
            <receive variable="tns:creditRequest"/>
         </exchange>
         <exchange name="creditAuthorized"
informationType="creditAuthorizedType" action="respond">
            <extends name="prepared"/>
            <send variable="tns:creditAuthorized"/>
            <receive variable="tns:creditAuthorized"/>
         </exchange>
         <exchange name="creditDenied"
informationType="creditDeniedType" action="respond">
            <extends name="refused"/>
            <send variable="tns:creditDenied" causeException="true"/>
            <receive variable="tns:creditDenied" causeException="true"/>
         </exchange>
      </interaction>
      
      <!-- catch the (application) exception - as an exception it will
abort the choreography and the finalizers are not accessible -->
      <exception name="handleBadCreditException">
         <extends name="handleRefusedException"/>
         <interaction channelVariable="tns:CreditResponder"
operation="creditDenied">
            <extends name="refused"/>
            <participate relationship="CreditReqCreditResp"
fromRole="tns:Responder" toRole="CreditRequestor"/>
         </interaction>
      </exception>
      
      <!-- Finalizers -->
      <!-- what to do if the credit is drawn down -->
      <finalizer name="drawDown">
         <extends name="confirm"/>
         <!-- if there is no application content to send, this could
just be an assignment to the statecapturevariable creditExtended -->
         <interaction channelVariable="tns:CreditRequestor"
operation="drawDown">
            <extends name="confirm"/>
            <participate relationship="CreditReqCreditResp"
fromRole="tns:CreditRequestor" toRole="CreditResponder"/>
            <record when="before">
               <source value="drawnDown"/>
               <target variable="CreditExtended"/>
            </record>
         </interaction>
      </finalizer>
      <!-- what to do if the credit is not used -->
      <finalizer name="replenish" case="cancel" default="true">
         <extends name="cancel"/>
         <!-- if there is no application content to send, this could
just be an assignment to the statecapturevariable creditExtended -->
         <interaction channelVariable="tns:CreditRequestor"
operation="replenish">
            <extends name="cancel"/>
            <participate relationship="CreditReqCreditResp"
fromRole="tns:CreditRequestor" toRole="CreditResponder"/>
            <record when="before">
               <source value="released"/>
               <target variable="CreditExtended"/>
            </record>
         </interaction>
      </finalizer>
   </choreography>


Choreology Anti virus scan completed

Received on Saturday, 30 October 2004 11:59:44 UTC