For Prevayler users

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

Database

Please note, Prevayler is a special object-oriented, in-memory database. It has advantages like:
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 OIDs instead of BOs

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

Data saved in GenericCommand consists of three parts:

Main ideas:

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 @@pat.bo 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 @@pat.bo'ed objects to org.nthx.pat.Identifiable and get its OID.

((Identifiable) myObject).getOID();

java.lang.reflect

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_).

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