Chapter 12. Hints and tips
12.1. General Tips
12.1.1. Using Transactions in Constructors
Examples throughout this manual use transactions in the implementation of constructors for new persistent objects. This 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. However, if the constructor transaction commits but is nested because some another transaction, which was started prior to object creation, is running, then the state is only written if all of the parent transactions commit.
On the other hand, if the constructor does not use transactions, inconsistencies may arise in the system. 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 a transaction.
Example 12.1. Transactions causing System Inconsistencies
AtomicAction A = new AtomicAction(); Object obj1; Object obj2; obj1 = new Object(); // create new object obj2 = new Object("old"); // existing object A.begin(0); obj2.remember(obj1.get_uid()); // obj2 now contains reference to obj1 A.commit(true); // obj2 saved but obj1 is not
Here, 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
method of obj2
is invoked, the object is activated and the Uid of obj1
is known. 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 some action later in the application, it will never be saved. However, if the constructor would have used an atomic action, the state of obj1
would have automatically been saved at the time it was constructed, preventing this inconsistency.
12.1.2. More on the save_state
and restore_state
Methods
JBoss Transaction Service may invoke the user-defined
save_state
method 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 especially true if it uses atomic actions. All of the variables saved by save_state
are correctly initialized.
Use caution when writing the
save_state
and restore_state
methods, to ensure that no transactions are explicitly or implicitly started. The reason is that JBoss Transaction Service may invoke the restore_state
method as part of its commit
processing, causing the execution of an atomic transaction during the commit
or abort
phase of another transaction. This may violate the atomicity properties of the transaction being committed or aborted, so it is discouraged.
To support crash recovery for persistent objects, all
save_state
and restore_state
methods of user objects need to call the super.save_state
and super.restore_state
.
12.1.3. Packing Objects
All of the basic types of Java, such as int and long, can be saved and restored from an
InputObjectState
or OutputObjectState
instances by using the pack
and unpack
methods provided by InputObjectState
and OutputObjectState
. However, you should handle packing and unpacking objects differently, because packing objects brings in the additional problems of aliasing. Alias means that two different object references may actually refer to the same item. See the Example 12.2, “Aliasing Problem with Packing Objects”.
Example 12.2. Aliasing Problem with Packing Objects
public class Test { public Test (String s); ... private String s1; private String s2; }; public Test (String s) { s1 = s; s2 = s; }
Here, both s1 and s2 point to the same string, and a naive implementation of the
save_state
method has the potential to copy the string twice. From the perspective of the save_state
method, this is merely inefficient. However, it would cause the restore_state
method to unpack the two strings into different areas of memory, destroying the original aliasing information. JBoss Transaction Service packs and unpacks separate object references.