Time for action – triggering compensation for the BPEL process

Carry out the following steps:

  1. Click on the BPEL process and then click on the following Add CatchAll icon:
    Time for action – triggering compensation for the BPEL process
  2. Once this is done, the <catchAll> activity will be added to the BPEL process, as follows:
    Time for action – triggering compensation for the BPEL process
  3. Within the <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:
    Time for action – triggering compensation for the BPEL process
  4. We configured to compensate the child scopes of the BPEL process. As the last step, we respond to the user notifying that the BPEL process was compensated. This is implemented by manipulating 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.
  5. To manipulate outputVariable, use an expression as shown in the following screenshot. The <result> element in outputVariable is assigned to 'Process faulted and has been compensated':
    Time for action – triggering compensation for the BPEL process
  6. Add an <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:
    Time for action – triggering compensation for the BPEL process

The final BPEL process looks like the following:

Time for action – triggering compensation for the BPEL process

What just happened?

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.

Implementing compensation handlers

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>

Triggering compensation handlers

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:

  • <compensateScope>: This activity triggers <compensationHandler> of a specific child scope
  • <compensate>: This activity triggers <compensationHandler> of all child scopes

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>

The execution of multiple compensation handlers

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.

The default compensation handler

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>

Have a go hero – compensating specific scopes

Update the sample BPEL process such that it compensates each specific scope (registerBookOrder and initiateCreditCardTransaction) one by one.

Pop quiz

Q1. What is the difference between fault handlers and compensation handlers?

Q2. Which construct does not support to specify <compensate> and <compensateScope>?

  1. <catch>
  2. <catchAll>
  3. <eventHandlers>
  4. <compensationHandler>
  5. <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?

  1. It is possible to define <compensationHandler> for <process>
  2. A compensation handler of a scope should be defined immediately before <faultHandlers>
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.159.104