Introduction to the Preclipse plugin

Preclipse is a plugin for the popular Java IDE Eclipse (www.eclipse.org). It provides support for the development of prevalent applications using the prevalence layer Prevayler for Java (www.prevayler.org).

About object prevalence

For many years now, relational databases are used to store business data in RAM or on disk, keeping it safe from server crashes and, for smaller applications, persistent during the time the application is not running.

The relational approach, however, does not really fit into modern object oriented software design; making it necessary to translate between object oriented and relational models, which is a error-prone and time consuming task. Therefore, new approaches had to be found which are more suitable for the object-oriented programming paradigm.

A very simple approach, ranging on one side of the scale, is the concept of serialization. Built into most programming languages (for example, using the Serializable interface in Java), serialization allows for storing complete object structures on disk and loading them again, recreating the object lattice. This approach is pretty simple; while it serves its purpose for small applications, it most certainly does not for larger, and mission-critical, applications.

On the other end of the scale, object-oriented databases can be found. They come with a large overhead, suitable for applications which deal with enormous amounts of data. While they certainly do require less effort from the programmer in comparison to relational databases, the implementation needed still tends to be very complex.

Object prevalence is a technology which lies in-between these two extremes, suitable for small to medium-complex applications. It is based on the assumption that all business object data of an application fits into RAM, which is indeed the case for many applications, both client- and server side. To keep the data safe from server crashes and during the time applications are not running, the business data is written to disk in certain intervals (called “snapshots”). Changes to the business data between those intervals are stored on disk, too (in form of “transactions”), to enable the complete re-creation of the business data on application reload.

For the targeted applications, object prevalence is very simple to use, as it does not impose a large overhead on the programmer; it is also very fast compared to relational and even object oriented databases.

As with object-oriented databases, a certain piece of software is required to provide the functionality for the approach on data persistence. Prevayler (www.prevayler.org) is a prevalence layer for Java providing all the functionality needed to implement prevalent systems in Java. During the time of this writing, replication is being implemented into Prevayler, making it suitable for distributed applications.

Task when writing a prevalent application

Despite its simplicity, writing a prevalent application required some thought and some extra coding to allow the prevalence layer to take snapshots and provide persistence between snapshots using transaction data. Some common tasks in writing a prevalent application using Prevayler are:

“Boot-strapping”

Every system requiring persistence has business objects which represent the model, that is the data of the application. In prevalent systems, business objects must eventually be contained within a top-level business object, the prevalent system root. This approach follows the composite pattern, as each BO may contain other BOs and so on.

Besides this prevalent system root, an instance of Prevayler must be created and associated with the prevalent system root to provide snapshot and transaction functionality.

Implementing business objects

The business data is one of the main parts of a prevalent system. Every BO needs to be assigned a unique ID, which makes it unique through application reloads and within persistent transactions. BOs must be contained within other BOs or, eventually, the prevalent system root (which is a BO itself). All BOs must be serializable to allow for snapshot creation.

Implementing transactions

Every change to a business object must be incorporated into a transaction, that is, a specific “command” object which, so to speak, incorporates change. There are three basic types of those transactions,

Note that there can be additional transactions which vary from application to application. In prevalent systems, transactions are normal classes in which just about anything can take place. All transactions must be serializable allowing Prevayler to store them on disk.

Testing the system

Every system needs to be tested before delivery. There already are a lot of tools which support testing, like debuggers, loggers like log4j or the Junit framework. Those techniques apply to prevalent systems as well. However, there are certain techniques which will make testing of prevalent systems more efficient.

First, as there are certain patterns one must follow when implementing prevalent systems with Prevayler, there are a few common mistakes which should be avoided. For example, inside transactions, BOs must only be accessed using their unique ID, not their object identity, as the latter may change during persistence operations. Also, fields of BOs may not be changed outside of transactions, or else the change will not survive an application reload.

While debugging, it is interesting to see what kind of information was serialized into snapshot and transactionlog-files by Prevayler. Special tools – based on reflection – are able to display this information

An Eclipse plugin to support the development of prevalent systems using Prevayler: Preclipse

To ease the development of prevalent applications, we have created the Preclipse plugin. It automates many tasks during the development phase of a prevalent system. Besides that, it provides functionality for testing and debugging prevalent systems which are hinted at above.

The Preclipse plugin fully integrates into Eclipse (Eclipse 3.0 Final) and provides the following functions.

Creation of prevalent applications

The plugin adds a new project type to Eclipse: The “Prevalent Java Project”. Basically, it is a Java project with additional features specially designed for prevalent applications.

New prevalent projects can be created using a new “New project” wizard, which also creates a main class, a prevalent system root, a data directory and the initial code to set up the system and a separate thread taking snapshots in regular intervals.

The project is, later on, completely configurable via a new project properties page.

Creation of BOs and transactions

The principle structure of BOs and transactions is always the same. A BO is contained within another BO (the prevalent system root being the top-level-BO) which assigns unique IDs to its children. Every BO needs at least one “create transaction”, during which the BO instance is assigned an ID and stored inside its parent BO.

Creating BOs and their three standard transactions (create, modify, and delete) normally means writing a lot of stupid code. The Preclipse plugin automates this task, as it provides wizards to create both the BOs including a mechanism for creating and assigning unique IDs as well as wizards for creating transactions.

Support for debugging

As pointed out above, there are some common mistakes when creating prevalent systems. Each prevalent project managed by Preclipse comes with its own prevalent nature and prevalent builder, which automatically scans the project for those errors and provides hints (markers and problem descriptions), to the programmer.

The Preclipse plugin also features viewers for snapshot and transactionlog files. Simply opening them inside Eclipse brings up a tree view of their contents. In addition to the functionality described above, there are some small tools assisting the developer in repetitive tasks (resetting the prevalent system, reverting to a previous state etc.).

Using Preclipse

Download Preclipse! Or visit our step-by-step-guide for creating a sample prevalent system.