Business activity API
Use the business activity application programming interface (API) to create business activities and compensation handlers for an application component, and to log data required to compensate an activity if there is a failure in the overall business activity.
Overview
The business activity support provides a UserBusinessActivity API and two interfaces: a serializable.CompensationHandler interface and a CompensationHandler interface. Each interface has two exceptions: RetryCompensationHandlerException and CompensationHandlerFailedException. We can look up the UserBusinessActivity interface from the application server JNDI at java:comp/websphere/UserBusinessActivity. For example:
InitialContext ctx = new InitialContext(); UserBusinessActivity uba = (UserBusinessActivity) ctx.lookup("java:comp/websphere/UserBusinessActivity");Use the getId method to access the unique identifier for the business activity that is currently associated with the calling thread. The identifier is the same as the one generated for the business activity scope at run time and used for information, warning, and error messages. For example, the application can use the identifier in audit or diagnostic messages, and it is possible to correlate between application-generated and runtime-generated messages.
InitialContext initialContext = new InitialContext(); UserBusinessActivity uba = initialContext.lookup("java:comp/websphere/UserBusinessActivity"); … String activityId = uba.getId(); if (activityId == null) // No activity on the thread else // Output audit message including activity idIf an application component runs work that might require compensating upon failure in the business activity, provide a compensation handler class that is assembled as part of the deployed application. This Java class must implement one of the following interfaces:
- com.ibm.websphere.wsba.serializable.CompensationHandler, which takes a takes a parameter of a serializable object
- com.ibm.websphere.wsba.CompensationHandler, which takes a parameter of a Service Data Object (SDO)
Typically, applications that already have their data available in DataObject format will use the CompensationHandler interface, and applications that do not will use the serializable.CompensationHandler interface. Both interfaces support the close and compensate methods.
An application must register a compensation handler implementation that works with the type of compensation data (serializable object or SDO) that the application uses. If there is a mismatch between the type of data that the application component uses and the compensation handler implementation, there is an error.
During normal application processing, the application can make one or more invocations to the setCompensationDataImmediate or setCompensationDataAtCommit methods, passing in either a serializable object or an SDO that represents 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 stored in either the serializable object or the SDO DataObject; when 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 way, for example by undoing changes made to database rows if there is a failure in the business activity. We associate the compensation handler with an application component using the assembly tooling, such as Rational Application Developer.
Active and inactive compensation handlers
You implement the serializable.CompensationHandler or CompensationHandler interface for any application component that executes code that might have to be compensated within a business activity scope. Compensation handler 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 initially be inactive until the transaction commits, at which point the compensation handler becomes active (see the following section). A compensation handler registered outside a transactional UOW always becomes active immediately.
When a business activity completes, it drives only active compensation handlers. Any inactive compensation handlers associated with the business activity are discarded and never driven.
Logging compensation data
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 when the business activity completes. The application calls one of these methods, depending on whether it expects transactions to be part of the business activity.
- setCompensationDataAtCommit()
Call the setCompensationDataAtCommit method when the application expects a global transaction on the thread.
- If a global transaction is present on the thread, the CompensationHandler object is initially inactive. If the global transaction fails, it rolls back any transactional work done within its transaction context in an atomic manner, and drives the business activity to compensate other completed UOWs. The compensation handler does not have to be involved. If the global transaction commits successfully, the compensation handler becomes active because if the overall business activity fails, the compensation handler is required to compensate the durable work that is completed by the global transaction. The setCompensationDataAtCommit method configures the CompensationHandler instance to undertake this compensation function.
- If a global transaction is not present when the setCompensationDataAtCommit method is called, the compensation handler becomes active immediately.
For example, for an SDO, and using the same business activity instance as in the previous example:
DataObject compensationData = doWorkWhichWouldNeedCompensating(); uba.setCompensationDataAtCommit(compensationData);
- setCompensationDataImmediate()
Call the setCompensationDataImmediate method when 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 that is not governed by the transaction. An example of this type of work is sending an email. The compensation handler must be active immediately so that if a failure occurs in a business activity, this non-transactional work is always compensated.
For example, for a serializable object, and using the same business activity instance as in the previous example:
Serializable compensationData = new MyCompensationData(); uba.setCompensationDataImmediate(compensationData);Although these two compensation data logging methods, if called in the same enterprise bean, use the same compensation handler class, they create two separate instances of the compensation handler 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 a compensation handler instance is already added to the Business Activity using one of these methods, and then the same method is called, passing in null as a parameter, that compensation handler 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 compensation handler instance to the business activity when a compensation data logging method is called for the first time by the enterprise bean that uses that business activity. At the same time, a snapshot of the enterprise application context is taken and logged with the compensation data. When the business activity competes, all the compensation handlers that were added to the business activity are driven to compensate or close. The code that we create in the CompensationHandler or serializable.CompensationHandler class is guaranteed to run in the same enterprise application context that was captured in the earlier snapshot.
For details about the methods available in the business activity API, see the topic about additional APIs.
Related:
Web Services Business Activity support in the application server Transaction compensation and business activity support Configure a server to use business activity support Create an application that uses the Web Services Business Activity support Additional Application Programming Interfaces (APIs)