Hello
Ivana,
Could
you please clarify the following paragraph:
"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."
In
this paragraph when you say "did not complete", do you mean "did
not complete successfully". I am assuming the faults will
be generated ONLY by activities that are actually completed and not
by activities still in RUNNING state?
As
I understand a BPEL process engine would only evaluate the
<completeCondition> for a process instance everytime an activity within in
the <flow> completes (SUCCESSFULLY or with a FAULT).
thanks,
-Vinky
-----Original Message-----
From: Trickovic, Ivana
[mailto:]
Sent: Saturday, September 11, 2004
5:10 PM
To: Alex Yiu; Axel Martens
Cc: Frank Leymann;
Dieter Roller; Dieter Koenig1; ''; '';
''
Subject: 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]