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

From
Trickovic, Ivana <>
Date
2004-09-11T22:09:59+00:00
ID
Thread
RE: [wsbpel] Issue 6 - Rough draft of proposal for vote
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]