JBoss.orgCommunity Documentation

Chapter 5. Hints and tips

5.1. General
5.1.1. Using transactions in constructors
5.1.2. save_state and restore_state methods
5.2. Direct use of StateManager

Examples throughout this manual use transactions in the implementation of constructors for new persistent objects. This is deliberate because it guarantees correct propagation of the state of the object to the object store. The state of a modified persistent object is only written to the object store when the top-level transaction commits. Thus, if the constructor transaction is top-level and it commits, the newly-created object is written to the store and becomes available immediately. If, however, the constructor transaction commits but is nested because another transaction that was started prior to object creation is running, the state is written only if all of the parent transactions commit.

On the other hand, if the constructor does not use transactions, inconsistencies in the system can arise. For example, if no transaction is active when the object is created, its state is not saved to the store until the next time the object is modified under the control of some transaction.


The two objects are created outside of the control of the top-level action A. obj1 is a new object. obj2 is an old existing object. When the remember operation of obj2 is invoked, the object will be activated and the Uid of obj1 remembered. Since this action commits, the persistent state of obj2 may now contain the Uid of obj1. However, the state of obj1 itself has not been saved since it has not been manipulated under the control of any action. In fact, unless it is modified under the control of an action later in the application, it will never be saved. If, however, the constructor had used an atomic action, the state of obj1 would have automatically been saved at the time it was constructed and this inconsistency could not arise.

TxCore may invoke the user-defined save_state operation of an object at any time during the lifetime of an object, including during the execution of the body of the object’s constructor. This is particularly a possibility if it uses atomic actions. It is important, therefore, that all of the variables saved by save_state are correctly initialized. Exercise caution when writing the save_state and restore_state operations, to ensure that no transactions are started, either explicitly in the operation, or implicitly through use of some other operation. The reason for this restriction is that TxCore may invoke restore_state as part of its commit processing. This would result in the attempt to execute an atomic transaction during the commit or abort phase of another transaction. This might violate the atomicity properties of the transaction being committed or aborted, and is thus discouraged. In order to support crash recovery for persistent objects, all save_state and restore_state methods of user objects must call super.save_state and super.restore_state.

The examples throughout this manual derive user classes from LockManager. These are two important reasons for this.

However, if you only require access to TxCore's persistence and recovery mechanisms, direct derivation of a user class from StateManager is possible.

Classes derived directly from StateManager must make use of its state management mechanisms explicitly. These interactions are normally undertaken by LockManager. From a programmer's point of view this amounts to making appropriate use of the operations activate, deactivate, and modified, since StateManager's constructors are effectively identical to those of LockManager.