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

From
Alex Yiu <>
Date
2004-09-14T08:16:25+00:00
ID
Thread
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]