<< View previous version | view page history | view next version >>
h3 About Rollbacks
To us, a rollback is a forgiving way to let you be a bit sloppy in your transactions: you can try out things, and if they break, the system rolls back the changes and pretends nothing happened. We are not encouraging you to be sloppy, though: sometimes, trying something out and rolling back the changes if bad things happen is the only way to do things, or is significantly better than checking all the preconditions before mutating the state of the system.
Rollbacks were, and still are, a much discussed feature in Prevayler. Most of the developers agree that supporting rollback is not really necessary, but some edge cases (such as some transactions dealing with external resources) asked for a better level of support. Still, it's recommended that you use rollback sparingly, particularly when the use of this feature would save you lots of coding effort.
h3 Transaction Censors
Prevayler uses the concept of a Transaction Censor to implement rollbacks. When a transaction is censored, it is not saved to the transaction logs, and thus can be considered as not executed.
The org.prevayler.implementation.publishing.censorship.TransactionCensor interface is defined as follows:
An error occurred: http://cvs.codehaus.org/viewcvs.cgi/*checkout*/prevayler/src/main/org/prevayler/implementation/publishing/censorship/TransactionCensor.java?root=prevayler. The system administrator has been notified.By default, transaction censorship is enabled. If you want to turn it off - that is, you don't want any rollback support at all, call PrevaylerFactory.configureTransactionFiltering(false) before creating your Prevayler instance.
h3 Kings and Food Tasters
The current implementation of the transaction censor uses the ancient analogy of a "food taster" that tries the food before the king can eat it. If the food taster dies from poisoning, the king is safe, and a new food taster is hired (it's a tough job, isn't it?). In Prevayler, the food taster is a deep-copy of your prevalent system. That is, the food taster contains an exact copy of your "real" objects.
The transactions are then tried in this copy of your system, and if they succeed, it's also executed on the "king" system. If it fails, the transaction is "censored", and the food taster dies, being lazily replaced with a new one. This is why we do not recommend widespread usage of rollbacks in Prevayler systems; it doubles the amount of memory required, and does at least twice as much processing per transaction. Systems with lots of transactions rolling back are almost guaranteed to be dog slow, as deep-copying both the prevalent system and transaction again everytime the food taster dies requires that you cope with the (de)serialization time of your whole object graph into a byte array, and then back again. We chose this implementation because it is the safest possible, not because it's the fastest one, and it doesn't introduce any new restriction or dependency (e.g., an AOP library) into the system.
