ONJava.com -- The Independent Source for Enterprise Java
oreilly.comSafari Books Online.Conferences.

advertisement

AddThis Social Bookmark Button

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.

Creating a transaction
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).

Setting up the transaction
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 Item to 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.

Snapshot and transaction log
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.

Viewing a snapshot and a transaction log

Viewing a snapshot and a transaction log
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.

Deleting snapshots and transactions
Figure 11. Deleting snapshots and transactions

Pages: 1, 2, 3, 4, 5

Next Pagearrow