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