Creating transactions. You can begin a new TopLevelTransaction with:
Transaction begin: 'MyTransaction'.
Creating nested transactions. You can begin a new nested transaction by sending #beginChild: to an existing transaction:
aTransaction beginChild: 'MyChildTransaction'
Creating named transactions. Transactions can also have names to identify them in debugging and to aid in collision management. Refer to Transaction overview for more details.
Commit and rollback strategies. Transactions can be ended with a variety of commit and rollback methods which allow the specification of success and failure actions. Refer to Transaction API for more details.
Transaction isolation policies. Transaction isolation policies can be specified for each Transaction. These policies control the behavior of transaction view version copying, merging, and promotion to the shared view.
ObjectExtender Parts
Several parts are available to enable you to work with transactions visually.
SharedTransaction. This part represents a distinguished or singleton instance of the SharedTransaction.
TopLevelTransaction. The TopLevelTransaction part represents a top level transaction. When this part is used in a composition editor it will create the top level transaction during the initialization phase of the view. This helps to ensure that the view's current transaction has been switched to the top level transaction before any of the connections are initialized.
TransactedVariable. In some circumstances, the applet or view is only working with a single current transaction. In this case the standard variable part (supplied in VisualAge) can be used to allow objects to be connected together and to the user interface parts. In some views, however, there may be several active transactions and the programmer needs to ensure that a specific variable on the view is "pegged" to a given transaction. This is done with the TransactedVariable part. The transacted variable has all of the behavior of the standard variable part except that it has one additional property: transaction. When the transacted variable part is given a transaction it will ensure that all connections are done with that transaction as the current transaction. Having executed the connection, the previous current transaction will be resumed. This allows connections to be guaranteed to get and set the value of the object within the transacted variable that is for the transaction that has been specified, irrespective of what the current transaction is at the point when the connection is activated. With the standard VisualAge variable part , the current transaction would be the one in which the get or set method was executed.
BusinessTransaction In some view scenarios, when a transaction is committed, you may want the view to remain open, in other scenarios, you may want to close the view. For example, an OK button might commit a view's changes and close the view whereas a Save button might commit the changes and keep the view open.
Whenever a transaction is committed, its state changes from active to committed and its parent transaction will be resumed. Any attempt to resume the committed (or rolled back) transaction will cause a VapTransactionFailure exception to be thrown. The developer must therefore begin a new transaction to allow the user to remain in the view at the same transaction nesting level.
The business transaction caters for such a scenario. It has a read only property of transaction which it will lazily initialize to a new TopLevelTransaction (Lazy initialization means that the transaction is created when it is first asked for if it has not been previously created and is null). When its transaction is committed (either through the commit() and rollback() methods on the BusinessTransaction part or by the transaction being committed elsewhere) a fresh transaction will be created by the part. When the transaction is regenerated the part signals the transaction property (which is bound to the transaction event). If the transaction property of the BusinessTransaction is connected to the transaction property of a TransactedVariable this will cause the TransactedVariable to refresh itself with the version of its object in the new transaction and the user is allowed to continue working with the transacted variable's contents.
By default the BusinessTransaction will create a new TopLevelTransaction the first time its transaction property is retrieved. Rather than create this as a child of the SharedTransaction the part will create a private ReadOnly transaction that it uses as the parent of its transaction. The reason for this is that when a transaction is committed its parent will be resumed. If a TopLevelTransaction is committed the SharedTransaction will be resumed. The SharedTransaction is not able to have any new objects created into it, including read only objects that are newly read in from the data store. By having the ReadOnly transaction as the parent however ensures that in the gap between the transaction being committed and refreshed the current transaction is able to read and refresh objects. This behavior can be toggled with the property createReadOnlyParent on the part.
It is also possible to explicitly set the parent transaction that the BusinessTransaction part should use to create its child transaction. This is done through the writable property parentTransaction on the part. This allows views that have to support nested transactions to be constructed by connecting the transaction property of one BusinessTransaction to the parentTransaction property of another. The latter transaction will be a nested child of the former, and the BusinessTransaction parts will ensure that whatever combination of transactions get committed or rolled back that both parts have valid transactions that are nested from one another.
Because the business transaction lazily initializes its transaction when it is first asked for, there are some circumstances where this is done before the parent transaction is set. In this case it may be the desired behavior that the previously lazily initialized transaction (which will not be a child transaction of the new parent transaction) should be rolled back. This is the default behavior. If this is not the desired behavior, that is, when the parent transaction is set on the part any previously generated transactions are left active, the boolean property rollbackTransactionWhenParentChanges should be toggled.