Persistent Applications Toolkit

Choose font sizeNormal TextBigger TextHuge Text

For Prevayler users

Some of the topics below assume you have some knowledge of Prevayler


Please note, Prevayler is a special object-oriented, in-memory database. It has advantages like:
  • simplicity of use,
  • speed of accessing your data,
  • speed for searching your data,
  • data recovery after failure,
  • transactions

But it may have one disadvantage for your project: your data may not fit in memory to use it. Actual 64-bit architecture allows to use a lot of data. Are present JVMs prepared for memory hungry applications? Many people still don't know.

But facts are: my friends run ~100K of business objects on 32-bit machine and they fit in 2G of RAM.
I run a simple application consisting of 13.000 objects and with historical information of changes on the objects. JMeter load test of concurrent users searching data in the application just rocks!
The choice is yours..

How it happens that it works?

The answer is simple. Imagine there is only one, very generic command (transaction): org.nthx.pat.GenericCommand. It's purpose is just like any other Prevayler command.
  • stores information of objects which participate in transaction (*)
  • run 'execute' method, which involves your business logic
(*) - stores OIDs instead of BOs

Another part of systems takes care of storing/creating BOs themselves.

Data saved in GenericCommand consists of three parts:

  • business method name - command name
  • target object on which method is invoked (OID only)
  • arguments passed to business method (OIDs only)

Main ideas:

  • First snapshot of data is taken right after construction of ROOT object
  • Every BO is put into IdentityMap and stored within command right after construction
  • Every BO in argument list of a transaction is translated (recovered) to simple OID and OID is stored instead - prevents "baptism" problem

With this data saved, with proper order of every command executed, Prevayler users may safely use PAT - you're able to write ZERO Prevayler's commands (transaction).

Assume that I pass my object graph's root as an argument to transacted method. What then? It's insane to store it automatically!

Yes, that's true. That is why PAT tests whether argument is one of your business objects or not (you've specified inside BO's class comment for it, or @@pat.root for ROOT). If so, then I do not simply store arguments in GenericCommand. Instead I store only his OID (object identifier). During deserialising I restore original object based on his OID and pass it to method.

Keep in mind you cannot simply have any arguments in transactions.

Where do you get OID from?

AOP allows you to use so called 'introductions'. JBossAOP does this by so called Mixins.

I introduced IdentityMap into your root class. Keys in the map are OIDs of objects, and values are real objects from your world - business objects.

Do I have to set OIDs by myself?

No. PAT framework does this for you.

During creation of every BO PAT attaches OID to it and puts object into IdentityMap.

So the IdentityMap must be quite big..

Yes. It is. Number of objects it holds is even bigger than number of your business objects. This is so, because _every_ BO is put there. Even those which you create only temporarily, or those that are not needed by you. There is feature of removing them from IdentityMap ( WeakHashMap might help - but it isn't Serializable)

Can I get OID for my object?

Yes, you can. Although it is not necessary to use them or even to know about them.

Cast any of your'ed objects to org.nthx.pat.Identifiable and get its OID.

((Identifiable) myObject).getOID();


Because I've chosen to make only one command (transaction) - generic one, there must be some way to recover data from it and execute business logic - your original annotated method. There is no other way as through reflection. So: reflection will be used during reading (deserialising) of commands (_transactions_). Logo

Revision: $Id: prevayler.gtml 3721 2005-06-09 23:40:24Z nthx $
Generated with GTML