Some 'more, in-depth' information on Oracle BPEL PM, ESB and other SOA, day2day things

Saturday, March 11, 2006

BPEL transactions, part 2 - Understanding compensation

In yesterdays note, I talked a little bit about transactions, and how they are handled within the boundaries of a process instance. Today in part 2, we will dive a little bit more into the concepts of <compensation> activities.

As BPEL itself is considered to be stateless, Alex, one of my colleques and the fellows from the WSBPEL spec team, came up with the concepts of compensation.

Compensations consist of 2 parts,
the compensation handler, and the compensate activity

Defintion:

  • Each scope can have one compensation handler

  • A compensation handler defines an undo sequence for the scope it is bound to, for example "cancel flight"

  • A compensation handler can be called directly (by specifying a scope) or indirectly by a compensate activity



The usecase:
Consider a flow, where a user can pass a date and a location, and the flow will search for / book a flight - and afterwards try to book a hotel room.
Given the hotel is not available, the flight should be cancelled.

The solution:
As per above definitions the ReserveAirline scope will have a compensation handler attached, that contains the logic for canceling the previously booked flight.

<scope name="ReserveAirline">
<!-- define a compensation handler -->
<compensationHandler>
<!-- call cancel ticked -->
<invoke name="Invoke_CancelTicket"
partnerLink="AirlineBookingService"
portType="airline:airlineBooking"
operation="cancelSeat"/>
</compensationHandler>
<sequence name="Sequence_1">
<invoke name="Invoke_BookTicket"
partnerLink="AirlineBookingService"
portType="airline:airlineBooking"
operation="reserveSeat"/>
</sequence>
</scope>



The next step in this little sample happens within the scope, responsible for booking a hotel room ()

The operation to reserve a hotel room (reserveHotel) throws a fault if no room is avaiable for the given dates hotel:NoRoomAvailfault


<scope name="ReserveHotel">
<faultHandlers>
<catch faultName="hotel:NoRoomAvailfault"
<throw name="RollBack"
faultName="client:rollBackFault"/>
</catch>
</faultHandlers>
<sequence name="Sequence_2"
<invoke name="Invoke_ReserveHotel"
partnerLink="hotel"
portType="ReservationSystem"
operation="bookRoom"/>
</sequence>
</scope>



In the above code a catch block is defined to catch the specific fault we
expect and throws itself a rollBackFault to the parent scope, that will trigger the compensation, we have defined earlier.

The last part is is to define a catch block on the parent scope, that triggers in case of a rollbackFault and fires the compensation defined on the ReserveAirline scope.


<faultHandlers>
<!-- catch the rollback fault and call -->
<catch faultName="client:rollbackFault">
<compensate name="CompensateBoookings"
scope="ReserveAirline"/>
</catch>
</faultHandlers>



Having questions? send your feedback on Understanding compensation in BPEL PM here

0 Comments:

Post a Comment

<< Home