RE: [wsbpel] Issue 6 - Rough draft of proposal for vote

From
Trickovic, Ivana <>
Date
2004-09-14T14:44:41+00:00
ID
Thread
RE: [wsbpel] Issue 6 - Rough draft of proposal for vote
Alex,

 

At 
the moment, just one quick question. What do you mean by the following 
statement: "After this clarification of 
terminologies, I hope you can see how a branchCondition/completionCondition 
should and can distinguish a faulted scope from a successfully completed scope. 
That concept should be separated from the situation where a "flow" waits for all 
enclosed activities to end."

 

Do 
you mean that we should have two different flavors of the flow 
activity:

a) 
the flow activity (as it is currently defined, without completion condition 
semantics) 

b) 
a flow' activity with completion condition

 
I 
have a few other comments and will send them in another email. 

 

Regards,

 

Ivana

  
-----Original Message-----
From: Alex Yiu 
  [mailto:]
Sent: Dienstag, 14. September 2004 
  04:59
To: Trickovic, Ivana
Cc: Axel Martens; Frank 
  Leymann; Dieter Roller; Dieter Koenig1; ''; 
  ''; ''; Alex 
  Yiu
Subject: Re: [wsbpel] Issue 6 - Rough draft of proposal for 
  vote

Ivana,

Thanks for a very detailed reply. 
  
It's good that we have at least 3 common viewpoints. :-) 
  

Regarding "isComplete()" function:
My main concern is the 
  scoping of activity name used in that function. 

As far as I remember, 
  the name of activity does not need to be unique across all activities within a 
  BPEL definition. (See Section 11.1) The only uniqueness requirement we have in 
  the spec exists for compensation. That is we cannot have the same name for 
  <scope> of the same nested level. We can potentially extend the 
  uniqueness of activity name to say all sibiling activity must not share the 
  same name. But, we cannot extend the uniqueness across all activities. 
  

======================
<flow>
    
  <completionCondition> 
        
      (isComplete('A') or isComplete('B')) and 
  isComplete('C')
    </completionCondition> 
  
    <scope name="A"> <scope name="B"> ... 
  </scope> </scope> 
    <scope name="B" 
  />
    <sequence name="C" /> 
</flow> 
  
======================

After the execution flow, people would be 
  very tempted to use isComplete('A') in a switch/case condition. However, 
  isComplete('A') is not legal outside the <flow>. That is where some 
  potential problems and confusion come from. Hence, the usage value of 
  isComplete() is decreased. 

Besides <completionCondition> within 
  a <flow>, I cannot think of a usecase of "isComplete()".
That is why 
  I hesitate about this "isComplete()" function. 

Regarding 
  "IgnoreFault" function:

Quoted from spec from Section 
  12.5:
"A 
  flow 
  completes when all of the activities in the flow 
  have completed. Completion of an activity in a flow includes the possibility 
  that it will be skipped if its enabling condition turns out to be false (see 
  Dead-Path-Elimination). " 
  

Quote from spec from Section 13.4:
"The 
  completion of the activity of a fault handler, even when it does not rethrow 
  the fault handled, is never considered successful completion of the attached 
  scope and compensation is never enabled for a scope that has had an associated 
  fault handler invoked."

In your first example, from compensation 
  viewpoint, scope-A is considered "faulted", not a "successful completion". 
  

IMHO, the branchCondition should count <scope> activites only 
  which completed successfully based on the definition in Section 13.4. 
  

Since "complete" is an overloaded term, we may want to consider 
  replace "complete" with "end" in Section 12.5:
"A 
  flow 
  completes when all of the activities in the flow 
  have ended. End of an activity in a flow includes: (a) the possibility that it 
  will be skipped if its enabling condition turns out to be false (see Dead-Path-Elimination). (b) a faulted 
  scope activity" 

After this clarification of terminologies, I hope you 
  can see how a branchCondition/completionCondition should and can distinguish a 
  faulted scope from a successfully completed scope. That concept should be 
  separated from the situation where a "flow" waits for all enclosed activities 
  to end. 

Hence, ignoreFault semantics is really NOT necessary. We can 
  drop that semantics streamline the completionCondition proposal. 
  

Thanks!

Regards,
Alex Yiu

Trickovic, 
  Ivana wrote:

  
    
    

    
Alex,

    

    
Regarding 
    syntax: 

    
(1) I do 
    not see why not. An expression must evaluate to an integer.

    
(2) 
    Indeed.

    
(3) 
    Agree.

    

    
Regarding 
    function isCompleted():

    
The 
    proposal allows a completionCondition to be based on process variables (see 
    attribute expression). The idea of 
    function isCompleted('activity_name') is to be able 
    to check the state of any activity enclosed with a flow activity. The 
    function does not have to be specific to the flow activity. Activity 
    <flow> with completion condition is just an example, which motivates 
    to define it. The execution of an activity does not necessarily end 
    modifying a process variable. 

    

    

    
Regarding 
    the IgnoreFaults semantics:

    
I agree 
    that element <ignoreFaults> looks quite similar 
    to <faultHandlers> but has quite different behavior. It is indeed 
    the most controversial part of the proposal. Maybe we should start with the 
    problem we are trying to resolve.

    

    
The 
    specification is currently saying (see section 13.4): "... When a fault 
    handler is present, it is in charge of handling the fault. It might rethrow 
    the same fault or a different one, or it might handle the fault by 
    performing cleanup and allowing NORMAL PROCESSING to continue in the 
    enclosing scope.... "

    

    
Let's take 
    a look at the following example - it is a "normal" flow activity (without a 
    completion condition).

    

    
<flow>

    

    
   
    <scope name="A">

    
      
    <faultHandlers>

    
         
    <catch name="tns:my_fault">

    
            
    <empty/>

    
         
    </catch>

    
      
    </faultHandlers>

    
      
    <compensationHandler name="C">

    
      
    ...

    
      
    </compensationHandler>

    
      
    <sequence name="X">

    
      
    ...

    
      
    </sequence>

    
   
    </scope>

    

    
   
    <scope name ="B">

    
   
    ...

    
   
    </scope>

    

    
</flow>

    

    
The flow 
    activity will complete as soon as all enclosing activities/scopes complete. 
    If fault "tns:my_fault" is thrown within sequence X it will cause the 
    termination of the sequence (all active enclosing activities) and will 
    be caught by the fault handler defined in the scope A. The fault handler 
    will do nothing, the scope A will be deemed as ended abnormally 
    and compensation handler C will not be installed. The flow element will 
    count that the scope completed and continue with normal processing. 
    The current 
    semantics of the flow activity is that it waits for all concurrent 
    activities to complete. The completion also means that an enclosed 
    activity/scope may end abnormally. So I do not see how we can distinguish 
    the case of "N out of N" (current semantics of the flow activity) and "M out 
    of N".

    

    
Maybe one 
    way would be to use some process variables, for example (maybe this is also 
    your suggestion):

    

    
<variables>

    
   
    <variable name="incompleteA" 
    type="xsd:boolean"/>

    
   
    <variable name="incompleteB" 
    type="xsd:boolean"/>

    
<variables>

    
<assign>

    
   
    incompleteA="false"

    
</assign>

    
<assign>

    
   
    incompleteB="false"

    
</assign>

    
<flow>

    
   
    <completionCondition>

    
   
    ...

    
   
    </completionCondition>

    
   
    <scope name="A">

    
   
    <faultHandlers>

    
      
    <catch name="tns:my_fault">

    
         
    <assign>

    
            
    incompleteA="true" 

    
         
    </assign> 

    
         
    <empty/>

    
      
    </catch>

    
   
    </faultHandlers>

    
    
    <compensationHandler name="C">

    
      
    ...

    
    
    </compensationHandler>

    
    
    <sequence name="X">

    
      
    ...

    
     
    </sequence>

    
   
    </scope>

    
   
    <scope name ="B">

    
   
    ....

    
   
    </scope>

    
</flow>

    

    
So, if 
    sequence A experience some problem and fault tns:my_fault is thrown, fault 
    handler local to scope A will make sure that the flow activity may continue 
    with the normal processing and will at the same time identify that the scope 
    A ended abnormally. This approach is also possible but it requires a lot of 
    "programming" and users have to be aware of this kind of pattern. I prefer 
    more declarative approach even if it requires more time to give clear 
    wording. 

    
 

    
Regards,

    

    
Ivana

    
      
-----Original Message-----
From: Alex Yiu [mailto:]
Sent: 
      Montag, 13. September 2004 08:01
To: Trickovic, 
      Ivana
Cc: Axel Martens; Frank Leymann; Dieter Roller; Dieter 
      Koenig1; ''; ''; ''; 
      Alex Yiu
Subject: Re: [wsbpel] Issue 6 - Rough draft of proposal 
      for vote

Hi, 

Ivana, thanks for sending out 
      this proposal.
I believe a number of us (including me) like the 
      <completionConditon> construct from your proposal high level 
      speaking. 

After reading the proposal, I guess we need to work on a 
      number of details. I would like to ask a few questions / mention a few 
      points:

      
        
Minor syntax and semantics questions: 
        
          
Do we want to allow expression for branch attribute? instead of 
          just a constant integer? 
          
We may need to some minor syntax adjustment for expression 
          attribute because we have passed Isseu 13 already. 
          
If answers to the above question are yes, then the condition 
          syntax may become a choice (xsd:choice) of the following 
          two:
<condition 
          expressionLanguage="anyURI"?>boolean-expression</condition>
<branchCondition 
          expressionLanguage="anyURI"?>integer-expression</condition> 
          

        
About completionConditionFailure: it looks like a nice idea 
        so far ... 

        
About the new "isCompleted()" function:  I am not 
        against this function. But, I tend to think there are usually BPEL 
        variables being modifed as the execution result of a flow activity. (See 
        the train-or-plane-and-hotel example). Is it more typical to have 
        completionCondition to be evaluated on those variables? 
Also, after 
        the completion of the whole flow, it is not uncommon for people to have 
        logic to find out which branch is finished (especially when "or" is 
        involved in the condition). The "isComplete()" function would be 
        available only within the completionCondition within the flow. People 
        may get confused and attempt to use the "isComplete()" function outside 
        the flow. If the completionCondition relies on variables, the same logic 
        is applicable outside of the flow.

        
About the IgnoreFault semantics: I recall this ignoreFault 
        idea back to March F2F. With ignoreFault semantics, it essentially 
        introduces two brand new semantics. 
        
          
It turns <flow> into a semi-<scope> like construct 
          
It adds this new "ignoreFault" semantics: which catches certain 
          fault and the catching action will not cause any scope to be marked as 
          faulted. 

      I tend to think this "ignoreFault" functionality has quite a 
        heavy weight impact to <flow> and fault handling picture in BPEL. 
        If there is an alternative way to achieve similar business logic, I 
        would go for the alternative way.

Quoted from Ivana's 
        email:
"Not all 
        activities must complete in order the enclosing flow activity to 
        complete. The way to identify that an enclosed activity did not complete 
        is to propagate faults."

I agree with the first 
        sentence. But, I am not sure that propagating fault is the only way to 
        identify an enclosed activity did not complete. I would rather use a 
        scope as an activity enclosed by flow. If we wish to suppress any minor 
        fault which happens during the execution of the scope, then we can just 
        add a fault handler. If the fault that happen, the scope will be marked 
        as "faulted". 

The completeConditon can identify the "incomplete" 
        state of the scope by two ways:

        
          
completeCondition can be evaluated based on BPEL variables, which 
          are set to "incomplete" state by pre-flow initialization or related 
          fault-handler logic. 
          
branch-based condition will interprete a faulted scope as 
          "incomplete" branch and will not count them into the required N 
          branches. 

This will allow us to suppress minor fault with 
        or without the <completionCondition> construct. Please see the 
        following example. It is already legal and working today. It shows how 
        to suppress "foo:barFault" without the <completeCondition> 
        construct

<flow>
   <scope 
        name="A">
      
        <faultHandler>
         
        <catch faultName="foo:barFault" ... > ... </catch> 
        
      
        </faultHandler>
      
        <sequence> 
        
         ...  
        <invoke name="doA" ... /> ... 
        
      
        </sequence>
   
        </scope>
   <scope name="B"> ... 
        <!-- similar to A --> ... </scope>   
        
</flow>

If the invoke of "doA" triggers 
        "foo:barFault", the scope "A" will be marked as faulted. On the other 
        hand, scope "B" will be allowed to continue and complete. After scope 
        "B" is completed, the compensation handler of scope "B" will be 
        installed. And, the overall execution of flow is still considered a 
        normal completion. 

I hope I have illustrated we can achieve 
        similar logic without introducing a new "ignoreFault" construct and 
        concept to BPEL. 

What "completionCondition" does should be just 
        providing a way to pro-actively cancel/terminate other flows without 
        waiting to them to complete or to be faulted. 

      
        
About "Cancel-other-flows":  (Let me consolidate what I 
        am leaning towards so far.) We need to formal define the notion of a 
        "cancel-other-flows" mechanism. This mechanism is specified and 
        attached to <flow> construct (and future parallel forEach 
        construct).  When this mechanism is triggered by one of parallel 
        flows, it will cancel/terminate other parallel flows which are still 
        running, after the triggering flow is completed. If the other flow 
        activties are scope activities, the scope will be marked as cancelled. 
        

This mechanism will be triggered upon the completionCondition is 
        evaluated to be true. 

[Note: (a) since this mechanism is 
        triggered by without using any fault directly. This will again decrease 
        the need of "ignoreFault" construct (b) This mechanism will affect the 
        wordings of Issue 135 to an extent.]

[Question: again, should we 
        enforce scope-only activity when completionCondition is used? I tend to 
        say yes.] 

Thank you all for following and reading 
      this email thread!!! 

Regards,
Alex 
      Yiu
 

Trickovic, Ivana wrote:

      
        
        

        

        
Here is 
        a proposal for the completion condition - 
        it addresses some issues not tackled so far (at least not in case of 
        <completeCondition>). It is a version of the proposal for 
        completion condition for the bundle element. This proposal includes 
        comments from many people including Frank Leymann, Dieter Koenig, Dieter Roller and Satish Thatte. It does not mean 
        that they completely support the proposal - they may have issues with 
        any part of the proposal.

        

        

        
Completion condition

        
=====================

        
The 
        current semantics of the flow activity is that it waits for all 
        concurrent activities to complete. The completion also means that an 
        enclosed activity/scope may end abnormally or be skipped (e.g. the join 
        condition of the activity evaluated to false). If a fault is thrown 
        within an enclosed activity/scope and one of the local fault handlers 
        catch the fault (and does not rethrow the fault), the enclosed 
        activity/scope will be deemed to be completed (although ended 
        abnormally). If a fault is not caught by any local fault handler (or is 
        rethrown) the flow activity will terminate all active concurrent 
        activities and corresponding fault handler may be 
        initiated.

        

        
A 
        completion condition for the flow activity is needed for scenarios where 
        not all concurrent activities of a flow activity must complete in order 
        the flow activity to complete. Note: We are not talking about 
        "successful completion" of enclosed concurrent activities because that 
        would not be consistent with the semantics of the current flow activity. 
        

        

        
The 
        completion condition may have different flavors, such 
        as:

        
(1) N 
        out of M

        
(2) The 
        two most important requests completed

        
(3) A 
        Boolean condition operating upon process 
        variables

        

        
Not all 
        activities must complete in order the enclosing flow activity to 
        complete. The way to identify that an enclosed activity did not complete 
        is to propagate faults. We may distinguish between severe faults and 
        those that can be ignored. Severe faults cause the enclosing flow 
        activity (or more precisely, enclosing scope) to terminate the flow 
        activity, including all active concurrent activities, and corresponding 
        fault handler may be initiated. Other faults may be ignored - the flow 
        activity is "informed" that a concurrent activity did not complete but 
        still allows other active concurrent activities to continue with 
        execution. 

        

        
Ignore 
        semantics

        
=================

        
Faults 
        thrown within enclosed concurrent activities/scopes and not handled by 
        local fault handlers are rethrown. Enclosing <flow> element 
        decides which of these rethrown faults can be ignored. This new "ignore" 
        semantics should be part of the completion condition and should apply to 
        all enclosed activities. This new semantics does not introduce a new 
        fault handling mechanism. It is needed for identifying how many of the 
        enclosed activities failed.

        

        

        
Proposed syntax

        
================

        
<flow standard-attributes>

        
   
        standard-elements

        
   
        <completionCondition/>?

        
   
        <links>?

        
      <link 
        name="ncname">+

        
   
        </links>

        
   activity+

        
</flow>

        

        
<completionCondition>

        
   <conditions 
        branch="xsd:integer"?

        
               
        expression=xpath?/>?

        
   
        <ignoreFaults>?

        
      <fault 
        name="qname"? value="ncname"?/>* 

        
      
        <ignoreAll/>?

        
   
        </ignoreFaults>

        
</completionCondition>

        

        

        
Attribute branch is used to 
        specify a condition of flavor "wait for N out of M 
        activities to complete", or more precisely value N. Attribute expression is used to specify a Boolean 
        condition operating upon process variables or a condition of flavor "the two most 
        important requests completed". 

        

        
Both 
        conditions (branch and expression) may be
        specified at the same time. They will be checked when one instance of 
        the scope activity reaches the end. If at least one condition evaluates 
        to true all active instances will be terminated.

        
 

        
Element <ignoreFaults> specifies faults that may be ignored. Element fault is used to specify a 
        fault which may be ignored (fault name and fault data may 
        be specified). Element <ignoreAll> would mean that all 
        faults thrown/rethrown by any 
        concurrent activity/scope may be ignored. If this element is 
        specified <fault> element must 
        be omitted.

        
 

        
Completion condition failure

        
=============================

        
A new 
        standard fault, e.g. completionConditionFailure, should be introduced to 
        notify that the completion condition of a flow activity evaluated to 
        false (note: all concurrent activities have been completed). The fault 
        is thrown in the scope enclosing the flow element. 
        

        

        
Completion condition and links

        
==============================

        
There 
        should be no difference between a flow activity with a completion 
        condition and a flow activity without completion condition. For example, 
        if the completion condition fails all links leaving the flow activity 
        should have value "false" (or be reverted to a negative status). 
        

        

        
There 
        are just a few additional rules:

        
(1) 
        Let's assume enclosed activity A is the source of a link. If the 
        completion condition evaluates to true and activity A is not completed 
        it will be terminated and the value of the link will be set to 
        "false".

        
(2) 
        Let's assume enclosed activity A is the source of a link and the 
        activity failed but the fault is "ignored" by the enclosing flow 
        activity. The value of the link will be set to "false". 
        

        

        

        
New 
        function for completion condition of flavor "the two most important 
        requests completed"

        
============================================================================================

        
For 
        completion conditions of flavor "the two most important requests 
        completed" standard attribute "name" must be specified for all enclosing 
        activities in order to be able to distinguish them. In addition a new 
        function, e.g. isCompleted('activityName') must be introduced. The 
        semantics of the function is: if activity completed successfully the 
        function returns value true. 

        

        
Example

        
    <completionCondition 
        expression=

        
           
        "isCompleted('A') AND 
        isCompleted('B')"          
        

        
     
        </completionConditions>

        

        

        
Regards,

        

        
Ivana

        
 

        
          
-----Original Message-----
From: Alex Yiu [mailto:]
Sent: 
          Samstag, 11. September 2004 00:49
To: Axel 
          Martens
Cc: ''; Trickovic, 
          Ivana; ''; ''; 
          Alex Yiu
Subject: Re: [wsbpel] Issue 6 - Rough draft of 
          proposal for vote

Hi, Axel, 

Thanks for 
          liking parts of my proposal so far.
Actually, the idea of my 
          proposal is borrowed from a part of presentation from Ivana and Dieter 
          Roller in March F2F. I just generalize it to apply to <flow> 
          also. 

About using links or not: 
I don't have a huge 
          opposition to Axel's proposal which enriches the semantics of 
          joinCondition evaluation. However, it is not that difficult for people 
          to make mistakes in joinCondition. Look at the 2-out-of-3 example. The 
          join condition already gets so complicated. If people make a mistake 
          in their joinCondition, the whole flow can get struck for no good 
          reasons. (The completeCondition approach will less likely to have the 
          whole flow struck. Because, it does not introduce a new parallel 
          activity in the flow). But, if this is what Petri-net-oriented and 
          control-link-oriented audience really want, I can accept it in a 
          sense, as long as this is not the only way to achieve similar business 
          logic. 

About static vs dynamic parallelism:
Static 
          parallelism is basically <flow> construct in BPEL. Dynamic 
          parallelism is "parallel forEach" or "bundle". Issue 4 and 147 are 
          related issues. 
http://www.choreology.com/external/WS_BPEL_issues_list.html#Issue4
http://www.choreology.com/external/WS_BPEL_issues_list.html#Issue147

About 
          "Terminating still running tasks versus proceeding in control flow 
          while those tasks are
still running": 
I am not 100% that I 
          understand your question. Let me try to answer it anyway. The 
          completeCondition is about triggering termination of still-running 
          tasks. The "proceeding in control flow" (if I understand you 
          correctly) will be handled by an outter flow. [I guess it is related 
          to (hotel and (train or plane)) flow??]

About changes of 
          "forcedTermination" fault handler: 
If you got a chance to see 
          some recent emails on Issue 135, Satish has recently suggested to 
          remove the notion "forcedTermination" fault and replace its fault 
          handler with cancelHandler. Frank, Yaron, Edwin and I all agree with 
          this direction. Because, overloading fault with the concept of 
          "forcedTermination" is a "false economy" and it creates quite a bit of 
          unnecessary confusion. 

I don't think we should go back to this 
          route or even further overload the "forcedTermination" fault handler 
          semantics. Because, fault handling is way too generic and the changes 
          you mentioned will create even more confusion. (e.g. Will this change 
          of marking as "completed" apply to all "forcedTermination" fault 
          handler / cancel handler of all scopes? )

I guess most of us 
          agree that we should have a new mechanism to kill / do an early 
          completion of a flow in a nice and clean way. However, overloading a 
          standard fault handler does not seem to be the best one. I would 
          rather introduce a construct which is very specific to <flow> or 
          parallel-forEach. For example, this <completeCondition> 
          construct or maybe a new activity called <completeFlow />.  
          I will send out more emails on joint thinking of both Issue 6 and 
          Issue 135.  Please stay tuned. 
          

Thanks!

Regards,
Alex 
          Yiu

Axel Martens wrote:

          
Hi, 
            

I like the simplicity of the 
            syntax of Alex's proposal. Although, 
for me it is quite easy to model in terms of 
            links and join 
conditions, 
            and I want to keep my proposal alive (because of the 
            
minimal changes to BPEL's syntax 
            and semantics), it looks like a 
nice macro to provide more convenience to the 
            customers. 

Alex, could 
            you shortly explain to me, what do you mean by static 
            
and dynamic parallelism? How do you 
            handle the two different cases 
after evaluating the completeCondition: Terminating still 
            running 
tasks versus 
            proceeding in control flow while those tasks are 
still running (Sorry, I missed your previous 
            emails)? 

I agree to 
            Alex's opinion, that we need a mechanism to kill 
parallel flow nice and clean. This could be 
            done either by a new 
mechanism which does not throw a fault or by changing the 
            way 
fault are handled. I 
            have discussed already an example of the 
second case with Ivana, and I like to tell 
            you, what I have in 
mind. 
            Look at the following example: 

<scope name="scopeFlow"> 
  ... 
  <flow> 
    <link name="linkA"/> 
    <link 
            name="linkB"/> 

  
              <scope name="scopeA"> 
      ... 
      <invoke name="A" ...> 
            
        
            <source linkName="linkA" ...> 
      </invoke> 
    </scope> 
            

    <scope 
            name="scopeB"> 
  
                ... 
  
                <invoke name="B" ...> 
        <source 
            linkName="linkB" ...> 
      </invoke> 
    </scope> 
            

    <throw 
            name="C" faultName="bpws:forcedCompletion" 
          
             joinCondition="linkA OR linkB" 
            joinEvaluation="immediate"> 
        <target linkName="linkA" 
            ...> 
      
              <target linkName="linkB" ...> 
    </throw> 
            

  </flow> 
            
</scope> 

First, I explain the situation: In the 
            example above, activity C 
will be executed if one of the two activities A and B 
            was 
successfully completed. 
            Activity C throws the fault 
"forcedCompletion". Like each other fault, this forces the 
            scope 
"scopeFlow" to 
            terminate still running activities. Assume, there 
was a fault handler defined in this scope 
            which catches the fault 
"forcedCompletion" (omitted in here), the process continues 
            after 
scope "scopeFlow". A 
            problem arises, if scope "scopeFlow" should 
be compensated. Because it was exited from a 
            fault handler, no 
compensation handler was installed. 

Now, I explain my solution: In the example, I 
            have chosen a new 
"standard" 
            fault name: "forcedCompletion". The only necessary 
change is to allow a fault handler that 
            catches this fault to 
install a compensation handler for the same scope, i.e. to 
            mark 
the scope "scopeFlow" 
            as "completed" instead of "exited". 

The standard compensation mechanism will only 
            undo those 
("scoped") 
            activities within the scope, which actually have been 
            
successfully completed, i.e. scopeA 
            or scopeB or may be both. 

Axel. 
----------------------------------------
Axel 
            Martens

Post Doc Researcher
Component Systems Group
IBM 
            TJ Watson Research Center 
Hawthorne, NY (USA)
Phone: (914) 
            784-7480
E-mail:  
            

            
              
              

                Alex Yiu <> 
                  
                  
09/10/2004 12:10 AM 
                

                
                  
                    
                    

                      
                        
To

                      Alex Yiu <> 
                      

                    

                      
                        
cc

                      "Trickovic, 
                        Ivana" <>, 
                        Axel Martens/Watson/IBM@IBMUS, "''" 
                        <>, 
                        "''" 
                        <>, 
                        "''" 
                        <>, 
                        Alex Yiu <> 
                      

                    

                      
                        
Subject

                      Re: [wsbpel] 
                        Issue 6 - Rough draft of proposal for 
                    vote

                  
                    
                    

                      

                      

Hi, 

Here are some examples how to use 
            completeCondition to express similar business logic in Axel's 
            previous email: 

(A) "Select one out of three" example: 
            
<flow>
   <completeCondition 
            branch="1" />
   <invoke 
            name="CheckAirlineA" ... /> 
   <invoke 
            name="CheckAirlineB" ... />
   <invoke 
            name="CheckAirlineC" ... />
</flow> 

(B) 
            "Select two out of three" example: 
<flow>
  
             <completeCondition branch="2" />
  
             <invoke name="AskRefereeA" ... /> 
  
             <invoke name="AskRefereeB" ... />
  
             <invoke name="AskRefereeC" ... 
            />
</flow>

As you guys can see, the 
            completeCondition declaration is very straight forward and simple. 
            No complicated links and joinCondition usage. 

(C) "(Plane or 
            Train) and Hotel" example: It would become two flow constructed 
            (nested).

<assign> ... 
            <to variable="planeResult"></assign> 
  <!-- 
            initialize "planeResult" with NOT-OK value --> 
<assign> 
            ... <to variable="trainResult"></assign> 
  
            <!-- initialize "trainResult" with NOT-OK value --> 
            
<flow name="checkIterinary">
  
             <flow name="PlaneOrPlane">
    
              <completeCondition> 
        
               fn:planeOK(planeResult) or 
            fn:trainOK(trainResult)
      
            </completeCondition> 
      <invoke 
            name="CheckPlane" outputVariable="planeResult" ... />
  
                <invoke name="CheckTrain" 
            outputVariable="trainResult" ... /> 
  
             </flow> 
   <invoke 
            name="checkHotel" /> 
</flow>
<switch 
            name="bookingSwitch">
   <case> 
  
                 <condition> 
      
             (fn:planeOK(planeResult) or fn:trainOK(trainResult)) 
            and fn:hotelOK(hotelResult)
      
             </condition>
       <invoke 
            name="invokeBooking" ... />
  
             </case>
   <otherwise> 
  
                   <invoke name="writeInformation" ... 
            /> 
   </otherwise> 
            
</switch>

Please note that regardless whether we pick a 
            link-oriented approach or completeCondition approach: 
            
              
The initialization of result variables are needed 
              because of potential cancellation of one of the invoke between 
              train and plane 
              
The "fn:*()" represents the logic to determine 
              whether a traveling resource is available. They are used in either 
              the transitionCondition of links or the condition of switch/case. 
              
As you guys see, we don't need declare 
            to six links. The completeCondition and case-condition are much 
            simpler and easier to understand. 

I attach a diagram to 
            illustrate the above flows.

I guess we can still more time in 
            terms of refiniment of joinCondition evaluation. However, I don't 
            think that should be the only approach to achieve complete condition 
            related logic.

Thanks!!!

Regards,
Alex 
            Yiu

Alex Yiu wrote: 

Hi,

+1 to what Ivana said in general.

Few 
            points to add: 
            
              
Axel's proposed enhancement to control links 
              evaluation works to an extent for static parallelism  (e.g. 
              <flow>). However, control links do not work well in dynamic 
              parallelism (e.g. "parallel forEach" or "bundle"). I think the 
              notion of completeCondition (borrowed from Ivana and DK) is 
              general enough and it should be applied to both static and dynamic 
              parallelism. A general completeCondition mechanism will be easier 
              for BPEL users to learn. 
              
Even in a pure static parallelism case, 
              completeCondition has much better code clarity. It is more 
              declarative and easier for BPEL users to understand. It will 
              eliminate significant amount of joinCondition programming, which 
              may be error prone. (I will send another email later to show how 
              completeCondition can be used to express the same semantics of 
              Axel's example). 
              
In one of my previous emails, I also tried to use 
              a "macro" way to illustrate how outstanding running flows can be 
              cancelled by throwing a fault within a scope. The illustration has 
              the same compensation handler installation problem that Ivana has 
              pointed out. The "illustraction macro" does NOT carry a desirable 
              and intended semantics. We need to create / describe a new 
              mechanism to cancel parallel flow without throwing a fault. (That 
              was discussed briefly between Edwin and me at Oracle). 
            

Thanks!

Regards,
Alex 
            Yiu

Trickovic, Ivana wrote: 
Axel, 
  
I find the idea interesting. In fact, I was 
            discussing the completion condition issue with Dieter Koenig during 
            the last f2f meeting and his suggestion was also to try to resolve 
            this issue using links. And we identified that several changes need 
            to be done, including removing restriction for jonCondition, that 
            "the join condition is evaluated as soon as all incoming links of 
            the activity are determined" - so definitely "immediate" semantics 
            needs to be introduced. 
  
I have the following comments on your proposal. 
            
1. In your proposal you are 
            using a fault (bpws:forcedTermination) to terminate all active 
            parallel branches. But this changes the outcome of the flow 
            activity. It will always end abnormally and compensation handler (if 
            it is defined) will never be installed. Although completion 
            condition has evaluated to true and needed activities have completed 
            the enclosing flow activity will end abnormally. Is this really 
            intended semantics? 
  
2. Your 
            proposal does not address some pain points. For example, in case of 
            "N out of M", N<M there many possible "variations": 
            
(A) One enclosed activity may 
            experience problems but the <flow> activity may succeed 
            
(B) One of enclosed 
            activities may experience a severe error, which may have impact on 
            the <flow> activity 
The question is what to do with running activities? In the 
            latter case, reasonable behavior would be: if one enclosed activity 
            does not succeed other running activities should be cancelled and 
            the flow activity should try to recover. In the former case, we 
            should allow active parallel activities to complete their work. This 
            is not supported in your proposal. 
  
Regards, 
  
            
Ivana 
          

[stuff 
      deleted]