Use the business activity API to create business activities and compensation handlers for an application component, and to log data that is required for compensating an activity if there is a failure.
InitialContext ctx = new InitialContext(); UserBusinessActivity uba = (UserBusinessActivity) ctx.lookup(“java:comp/websphere/UserBusinessActivity”);
If an application component is running work that might require compensating upon failure, provide a compensation handler class that is assembled as part of the deployed application. This new Java class must implement the com.ibm.websphere.wsba.CompensationHandler interface, which supports the close and compensate methods, which take a parameter of a Service Data Object (SDO). During normal application processing, the application can make one or more invocations to the setCompensationDataImmediate or setCompensationDataAtCommit methods, passing in an SDO representing the current state of the work performed.
When the underlying unit of work (UOW) that the root business activity is associated with completes, all registered compensators are coordinated to complete. During completion, either the compensate or the close method is called on the compensation handler, passing in the most recent compensation data logged by the application component as a parameter. Your compensation handler implementation must be able to understand the data that is stored in the SDO DataObject; using this data, the compensation handler must be able to determine the nature of the work performed by the enterprise bean and compensate or close in an appropriate manner, for example by undoing changes made to database rows if there is a failure. You associate the compensation handler with an application component by using the assembly tooling, such as Rational Application Developer.
You implement the CompensationHandler interface for any application component that executes code that might need to be compensated within a business activity scope. CompensationHandler objects are registered implicitly with the business activity scope under which the application runs, whenever the application calls the UserBusinessActivity API to specify compensation data. Compensation handlers can be in one of two states, active or inactive, depending on any transactional UOW under which they are registered. A compensation handler registered within a transactional UOW might be initially inactive until the transaction commits, at which point it becomes active (see below). A compensation handler registered outside a transactional UOW always becomes active immediately.
When a business activity completes, it drives active compensation handlers only. Any inactive compensation handlers that are associated with the business activity are discarded and never driven.
The business activity API specifies two methods that allow the application to log compensation data. This data is made available to the compensation handlers during their processing upon completion of the business activity. The application calls one of these methods, depending on whether it expects transactions to be part of the business activity.
For example, using the same business activity instance as in the previous example:
DataObject compensationData = doWorkWhichWouldNeedCompensating(); uba.setCompensationDataAtCommit(compensationData);
Call this method if the application does not expect a global transaction on the thread.
The setCompensationDataImmediate method makes a CompensationHandler instance active immediately, regardless of the current UOW context at the time that the method is invoked. The compensation handler is always able to participate during completion of the business activity.
The role of the setCompensationDataImmediate method is to compensate any non-transactional work, in other words, work that can be performed either inside or outside a global transaction, but is not governed by the transaction. For example, sending an e-mail. The compensation handler must be active immediately so if a failure occurs within a business activity, this non-transactional work is always compensated.
Although these two compensation data logging methods, if called within the same enterprise bean, use the same CompensationHandler class, they create two separate instances of the CompensationHandler class at run time. Therefore, the actions of the methods are mutually exclusive; calling one of the methods does not overwrite any work carried out by the other method.
If such a method is called passing in null as a parameter, and a CompensationHandler instance was previously added to the Business Activity by the same method, that CompensationHandler instance is removed from the business activity, and is not driven to close or compensate during completion of the business activity.
As described previously, the business activity
support adds a CompensationHandler instance to the business activity when
a compensation data logging method is called for the first time by the enterprise
bean using that business activity. At the same time, a snapshot of the J2EE
context is taken and logged with the compensation data. Upon completion of
the business activity, all the compensation handlers that were added to the
business activity are driven to compensate or close. The code that you create within the CompensationHandler
class is guaranteed to run within the same J2EE context that was captured
in the earlier snapshot.
For details about the methods available in the business activity
API, see the WebSphere Application
Server application programming interface reference information.