OASIS Mailing List ArchivesView the OASIS mailing list archive below
or browse/search using MarkMail.


Help: OASIS Mailing Lists Help | MarkMail Help

wsbpel message

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]

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

Hi, Yaron,

Don't get me wrong. :-)
I don't want an over-engineered complete condition proposal either.

If you read my emails again, you can see:
  • I am for completionCondition (including the branchCondition version)
  • I am not so sure about "isComplete()" function value.
  • IMHO, ignoreFault is not necessary and it does not look like a good idea. (I feel that it is a "tail wagging the dog" situation).

Basically, completionCondition (and branchCondition) is an extended version of your orJoin="yes" proposal (eq. to branch="1"). That offers a very nice high-level abstraction of a complete condition, that can be applied to <flow>, serial and parallel version of forEach. That is a declarative approach.

On the other hand, "break" or its equivalents offers an imperative approach.

I think we should try to enable both, if feasible. Because, they are for different audiences. The declarative approach is more for business analysist. The imperative approach is more for programmers who wish to control fine details on how to end a flow.

The only catch of "break" is we need to nicely define the following:
  • the target of the "break"-jump (while, switch, scope, flow)?
  • its effect on sibiling flows, the compensation/fault handler states of parent scopes, the links of parent activities

Anyway, that will belongs to Issue 142 discussion thread.


Alex Yiu

Yaron Y. Goland wrote:
I believe that the complexity of the current proposal is well above the capabilities of what I expect to be the average BPEL programmer. Completion conditions, ignorable faults, new XPATH functions, etc. introduces a lot of complexity that I believe that average BPEL programmer would not be interested in dealing with.

We know from many decades of language experience that average programmers can deal with break/continue. I know from at least our own experience at BEA that users can deal with the concept of a flow where a break in the flow results in the other members of the flow being terminated in the BPEL meaning of the term.

Defining a break activity and specifying that if break is used in the context of flow then this means that the flow activity ends and any uncompleted members of the flow are terminated would both fit directly into BPEL's existing syntax and semantics and I believe be simple enough that the average programmer can handle it. I would therefore offer break (and it's relative 'continue') as an alternative.



Alex Yiu wrote:


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 :
          o Do we want to allow expression for branch attribute? instead
            of just a constant integer?
          o We may need to some minor syntax adjustment for expression
            attribute because we have passed Isseu 13 already.
          o If answers to the above question are yes, then the condition
            syntax may become a choice (xsd:choice) of the following two:

    * 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.
          o It turns <flow> into a semi-<scope> like construct
          o 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

       <scope name="A">
             <catch faultName="foo:barFault" ... > ... </catch>
             ...  <invoke name="doA" ... /> ...
       <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!!!

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>




      <link name="ncname">+






   <conditions branch="xsd:integer"?



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





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.



    <completionCondition expression=

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







    -----Original Message-----
    *From:* Alex Yiu [mailto:alex.yiu@oracle.com]
    *Sent:* Samstag, 11. September 2004 00:49
    *To:* Axel Martens
    *Cc:* 'edwink@collaxa.com <mailto:edwink@collaxa.com>'; Trickovic,
    Ivana; 'satisht@microsoft.com <mailto:satisht@microsoft.com>';
    <mailto:wsbpel@lists.oasis-open.org>'; 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.

    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.


    Alex Yiu

    Axel Martens wrote:


    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">
        <link name="linkA"/>
        <link name="linkB"/>

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

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

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


    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 Martens

    Post Doc Researcher
    Component Systems Group
    IBM TJ Watson Research Center
    Hawthorne, NY (USA)
    Phone: (914) 784-7480
    E-mail: amarten@us.ibm.com <mailto:amarten@us.ibm.com>

    *Alex Yiu <alex.yiu@oracle.com> <mailto:alex.yiu@oracle.com>*

    09/10/2004 12:10 AM

        Alex Yiu <alex.yiu@oracle.com> <mailto:alex.yiu@oracle.com>
        "Trickovic, Ivana" <ivana.trickovic@sap.com>
    <mailto:ivana.trickovic@sap.com>, Axel Martens/Watson/IBM@IBMUS,
    "'edwink@collaxa.com'" <mailto:%27edwink@collaxa.com%27>
    <edwink@collaxa.com> <mailto:edwink@collaxa.com>,
    "'satisht@microsoft.com'" <mailto:%27satisht@microsoft.com%27>
    <satisht@microsoft.com> <mailto:satisht@microsoft.com>,
    <mailto:wsbpel@lists.oasis-open.org>, Alex Yiu
    <alex.yiu@oracle.com> <mailto:alex.yiu@oracle.com>
        Re: [wsbpel] Issue 6 - Rough draft of proposal for vote



    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:
       <completeCondition *branch="1"* />
       <invoke name="CheckAirlineA" ... />
       <invoke name="CheckAirlineB" ... />
       <invoke name="CheckAirlineC" ... />

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

    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">*
               fn:planeOK(planeResult) *or* fn:trainOK(trainResult)
          <invoke name="CheckPlane" outputVariable="planeResult" ... />
          <invoke name="CheckTrain" outputVariable="trainResult" ... />
       *</flow> *
       <invoke name="checkHotel" /> *
    <switch name="bookingSwitch">*
           (fn:planeOK(planeResult) *or* fn:trainOK(trainResult))
    *and* fn:hotelOK(hotelResult)
           <invoke name="invokeBooking" ... />
             <invoke name="writeInformation" ... />
       </otherwise> *

    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

    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.


    Alex Yiu

    Alex Yiu wrote:


    +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).


    Alex Yiu

    Trickovic, Ivana wrote:
         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.

    [stuff deleted]

[Date Prev] | [Thread Prev] | [Thread Next] | [Date Next] -- [Date Index] | [Thread Index] | [List Home]