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

From
Alex Yiu <>
Date
2004-09-10T22:49:35+00:00
ID
Thread
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]