Carry out the following steps:
<catchAll>
activity will be added to the BPEL process, as follows:<catchAll>
activity, we can trigger <compensationHandler>
for all the child scopes by using the <compensate>
activity. However, before triggering it, add a <sequence>
activity called catchall, and within it, add a <wait>
activity with an interval of 30 seconds, so the user can monitor the status of the BPEL process before triggering <compensationHandler>
, as follows:outputVariable
using an <assign>
activity and sending the value of outputVariable
to the client using an <invoke>
activity. Let's add an <assign>
activity after the <compensate>
activity.outputVariable
, use an expression as shown in the following screenshot. The <result>
element in outputVariable
is assigned to 'Process faulted and has been compensated':<invoke>
activity after the <assign>
activity and configure it as shown in the following screenshot. It sends the modified value of outputVariable
back to the client:The final BPEL process looks like the following:
In the previous section, we completed the book ordering process. This BPEL process throws a fault from the throwFault
sequence, and the fault is caught by the catachAll
sequence. Then, within the catachAll
sequence, <compensationHandler>
of child scopes is triggered.
To implement the compensation, WS-BPEL 2.0 provides the <compensationHandler>
construct. Note that this construct can be defined only for a <scope>
or an <invoke>
activity.
This <compensationHandler>
of the scope is defined immediately after <faultHandlers>
:
<scope> <partnerLinks></partnerLinks> <messageExchanges></messageExchanges> <variables></variables> <correlationSets></correlationSets> <faultHandlers></faultHandlers> <compensationHandler> <!—Compensation activities --> </compensationHandler> <terminationHandler></terminationHandler> <eventHandlers></eventHandlers> </scope>
The other option of defining <compensationHandler>
is within an <invoke>
activity. This is more like a shortcut that allows a BPEL developer to specify a compensation for an <invoke>
activity without enclosing it in a <scope>
activity for the sake of specifying the compensation. We call it as an inline compensation handler:
<invoke ... > <compensationHandler> <!—Compensation activities --> </compensationHandler> </invoke>
Within <compensationHandler>
, we can specify an activity that has to be executed for compensation. This activity can either be a basic activity such as <invoke>
, or a structured activity such as <sequence>
or <flow>
. Consider the following code snippet:
<compensationHandler> <sequence> <assign>...</assign> <invoke ... /> <assign>...</assign> <invoke ... /> </sequence> </compensationHandler>
We have to use <compensationHandler>
to undo an activity that has completed normally, whereas <faultHandler>
is used to act upon an exception condition during the execution of an activity. The main purpose of a compensation is to undo a <scope>
or an <invoke>
activity.
WS-BPEL 2.0 provides two activities to trigger a compensation handler. They are as follows:
The <compensateScope>
activity is used to trigger the compensation of a specified child scope. The child scope is specified by the attribute named target
. The following example triggers a child scope named registerBookOrder
:
<compensateScope target="registerBookOrder"/>
The <compensate>
activity is used to trigger the compensation of all child scopes. The following example triggers the compensation handler of each completed child scope in a particular order:
<compensate/>
Now, we know the activities that enable you to trigger and compensate <compensationHandler>
, but where can we put them?
We can only use the <compensate>
and <compensateScope>
activities within the following constructs:
<catch>
<catchAll>
<compensationHandler>
<terminationHandler>
In the provided sample example, we used <catchAll>
to put <compensate>
to trigger the compensation:
<catchAll>
<sequence name="catchAll">
...
<compensate name="compensate"/>
...
</sequence>
</catchAll>
If we trigger a compensation handler for a scope, then it triggers compensation handlers for the completed and immediately enclosed scopes in the reverse order of completion. For example, in the sample BPEL process provided for this chapter, there are two scopes named registerBookOrder
and initiateCreditCardTransaction
, which are defined within a sequence called main
. The scope initiateCreditCardTransaction
will complete its execution after registerBookOrder
. Suppose we use a <compensate>
activity in the global fault handler. Then, compensation handlers of both the scopes get triggered in the reverse order. This means that the scope named initiateCreditCardTransaction
will compensate before the scope named registerBookOrder
.
We can define <compensationHandler>
only for an <invoke>
and a <scope>
activity. The visibility of <compensationHandler>
in a scope is limited to the inner <scope>
. If <compensationHandler>
is not defined for a given <scope>
activity, then the BPEL runtime cannot trigger all the compensation handlers defined within the enclosed <scope>
. Hence, the BPEL runtime implicitly specifies a default compensation handler, as shown in the following code. A default compensation handler compensates all inner scopes in the reverse order of their completion and rethrows the fault to the parent scope:
<compensationHandler> <compensate /> </compensationHandler>
Update the sample BPEL process such that it compensates each specific scope (registerBookOrder
and initiateCreditCardTransaction
) one by one.
Q1. What is the difference between fault handlers and compensation handlers?
Q2. Which construct does not support to specify <compensate>
and <compensateScope>
?
<catch>
<catchAll>
<eventHandlers>
<compensationHandler>
<terminationHandler>
Q3. What is the behavior of a compensation handler if it belongs to a scope that is not completed normally?
Q4. Which statement is true and which is false?
<compensationHandler>
for <process>
<faultHandlers>