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