Prevalence: Transparent, Fault-Tolerant Object Persistence
Pages: 1, 2, 3, 4, 5
Creating a Transaction
You haven't created all of the BO classes yet, but you can now
create a transaction so that you can check whether the system built
so far actually works. The first transaction you need is to add a
new Item to the system. Right-click on the
Item class (again, the class, not the source file) and
select Prevayler -> Create 'Create' transaction for
BO…" as shown in Figure 7.

Figure 7. Creating a transaction
In the Create Transaction dialogue, accept the
name ItemCreateTransaction, but deselect the fields to
be included in the constructor (see Figure 8).

Figure 8. Setting up the transaction
Clicking Finish creates a new class,
ItemCreateTransaction, which contains:
- A constructor, used to set up the properties of the
Itemto be added to the system. - A method,
executeAndQuery, which takes a prevalent system object as a parameter and actually performs the transaction.
Modify the code slightly to the following:
public class ItemCreateTransaction
implements TransactionWithQuery {
private Item item;
public ItemCreateTransaction(Item item) {
this.item = item;
}
public Object executeAndQuery(Object prevalentSystem,
Date executionTime)throws Exception {
Item it = ((PrevalentOrderSystem)prevalentSystem).
addItem(this.item);
return it;
}
}
This transaction takes a BO that is an instance of
Item (or any of its subclasses) as a parameter in its
constructor, and calls the addItem method of the
PrevalentOrderSystem to make it persistent. The
id field is set by the prevalent system.
Note that this transaction works slightly differently from the
way in which Preclipse's auto-generated transactions are intended
to work. The default approach is to take field values for the BO as
parameters in the constructor of the transaction, to let the
prevalent system create a new BO using an appropriate constructor
and to set the fields of the BO in the transaction. This is good if
you know what all of the fields in the BO will be, but not if the
transaction must deal with different types of BOs. You will use
the default approach for the Order BO later on.
Trying It Out
The system you have created so far can be used with any kind of
UI to create an application. For simplicity, the "application" here
will be some basic classes that store and retrieve some objects.
You already have a Main class that starts off a
snapshot thread.
Add a new class called Store to the project in the
usual way, using the following code. This will add three different
types of item, including a composite item, to the prevalent
system.
import org.prevayler.Prevayler;
import org.prevayler.PrevaylerFactory;
public class Store {
public final static String DATA_FOLDER = "data";
public static void main(String[] args) {
try {
final Prevayler prevayler =
PrevaylerFactory.createPrevayler(
new PrevalentOrderSystem(),
DATA_FOLDER);
prevayler.execute(new ItemCreateTransaction(
new BookItem(39.95,
"Java Database Best Practices",
"George Reese")));
System.out.println("BookItem added");
prevayler.execute(new ItemCreateTransaction(
new SoftwareItem(74.99,
"SuSE Linux Professional",
"9.2")));
System.out.println("SoftwareItem added");
SoftwareItem switem = new SoftwareItem(169.99,
"Red Hat Enterprise Linux", "4");
prevayler.execute(new ItemCreateTransaction(
new MultipackItem (switem,10, 0.2)));
System.out.println("MultipackItem added");
} catch (Exception e) {
e.printStackTrace();
}
}
}
To test this, run the Main class as a Java
application--this starts a snapshot thread. Now run the
Store class as a Java application, and create the
persistent objects.
How do you know that the objects have been stored? Shortly, you
will add a class that retrieves the stored objects, but Preclipse
provides another, convenient way of examining persistent data.
First, you need to terminate the snapshot thread. Select the
Console for the Main process and terminate the process
using the red terminate icon.
Now right-click on the data folder in the Package Explorer and
select the Refresh menu item. You should see at
least one transaction log and one snapshot listed, similar to
Figure 9.

Figure 9. Snapshot and transaction log
Double-click on the snapshot. The Preclipse Snapshot
Viewer should open and show the persistent data.
Similarly, the transaction log can be viewed in the
Transaction Log Viewer. Figure 10 shows views of a
snapshot and a transaction log for the data created by
Store. This snapshot was actually created after
restarting and then terminating Main again to make
sure the most recent data is included in it. The
ArrayList contains three objects, and
nextItemID is set to 4, as you would expect.


Figure 10. Viewing a snapshot and a transaction log
Querying the prevalent system for objects does not require a
transaction as the system is not changed. Add and run a class named
Retrieve to your project to retrieve and list all of the
Items. The code for Retrieve is shown
below. It simply uses the toString method of each
object to print some information about the object--the
id field, the class name, etc.
import org.prevayler.Prevayler;
import org.prevayler.PrevaylerFactory;
import java.util.List;
import java.util.Iterator;
public class Retrieve {
public final static String DATA_FOLDER = "data";
public static void main(String[] args) {
try {
final Prevayler prevayler =
PrevaylerFactory.createPrevayler(
new PrevalentOrderSystem(), DATA_FOLDER);
List items = ((PrevalentOrderSystem)
prevayler.prevalentSystem())
.getItems();
for (Iterator ii = items.iterator();
ii.hasNext();) {
Item currentItem = (Item) ii.next();
System.out.println(currentItem.toString());
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
The result of running Retrieve should be similar to
the following:
Reading data\0000000000000000001.transactionLog...
1 - class ordersystem.BookItem:100 in stock:
Java Database Best Practices
2 - class ordersystem.SoftwareItem:100 in stock:
SuSE Linux Professional
It is useful when building and testing the system to be able to delete existing snapshots and transaction logs. Preclipse makes this easy. Right-click on the top-level project folder in Package Explorer and select "Prevayler -> Delete all snapshots and transactions," as shown in Figure 11.

Figure 11. Deleting snapshots and transactions