Prevayler
The Open Source Prevalence Layer

Baptism Problem

Posted in Apr 16, 2008 by Tasos Zervos - Edit - History

The essential principle relating to the " baptism problem " is that business objects within Prevayler's protection should never leave Prevayler's protection. Abiding by that principle lets Prevayler take care of things like concurrency and transaction recovery consistently.

The implication of that principle is that the safest style of Prevayler usage is to always use Queries and Transactions for any access to the business objects, and never pass business objects as the results of queries or held in transactions. Prevayler makes sure that a Transaction will never run concurrently with a Query, simplifying the threadsafety of your application.

If you were to return a business object as the result of a query (or access one directly through the prevalentSystem () call), your first challenge would be that you are now responsible for more careful threadsafety, because Prevayler can no longer prevent transactions from running concurrently with other accesses to that object. You can do that if you like, just be aware of the consequences.

If you do go ahead and extract a direct reference to a business object, the real meat of the " baptism problem " is that you really cannot pass that object back in through a transaction and expect it to work, because during recovery from the transaction journal, each transaction is deserialized from the journal, which necessarily creates a new instance of the object rather than referring to the one protected inside Prevayler. This is a particularly troublesome problem because it might seem to be working fine as the system is running, but will break if you shut down the system and restart it from the journal.

(As it happens, Prevayler's internal pipeline always deserializes a copy of each transaction anyway, even when running for the first time, which helps to catch this kind of problem earlier.)

All this means is that transactions should carry some identifier of the business objects they want to interact with, rather than direct references to the objects, and then look up the object during execution within Prevayler.

As a special case, immutable objects such as String may be fine to pass in and out - - as long as you are not using their object identity (pointer equality) for anything meaningful - - because threadsafety is taken care of by the very fact that they ' re immutable.

As another special case, a transaction which is adding a new object may safely carry a business object, because there's no issue with object identity - - you're not trying to interact with an existing object. Even if the object is copied, it's okay, because you're treating it as a new object anyway. Just don't keep any references to that object outside of Prevayler - - once you've sent it in through a transaction, if you want to interact with it, you'll need to either use a Query or get it back out with the prevalentSystem () call in order to get the ultimate " real " object.

It's named like that because most new users end up having this problem when creating their first prevalent system, and after they're " baptized ", they rarely run into it again.

 

Comments


ok. but what is the connection to baptism?

- - KK

Posted in Mar 26, 2008 by 194.29.157.11

" What rules do I have to follow? "
...
" 4. Transactions can ' t carry direct object references (pointers) to business objects. This has become known as the baptism problem because it ' s a common beginner pitfall. "

(http://prevayler.org/wiki/Front%20Page)

Posted in Mar 26, 2008 by Tasos Zervos

It's named like that because most new users end up having this problem when creating their first prevalent system, and after they're " baptized ", they rarely run into it again.

Posted in Mar 26, 2008 by Tasos Zervos

Maybe KK is questioning the choice of name due to it's religious connotation?;)

Perhaps outside Christian predominant societies the word ' baptism ' is widely used as a synonym of ' initiation '?;)

- - Dan

Posted in Mar 26, 2008 by 82.152.145.234

is * not * widely used

- - Dan

Posted in Mar 26, 2008 by 82.152.145.234

I'm not Java programmer myself and never worked with Prevayler but Baptism problem could be solved. Of course Prevayler would need to use its own serialization code that would detect any objects that are already persisted by Prevayler and just serialize them as simple lookup ID instead of whole object tree as standard JAVA serialization does I guess.

what do you think?

- - lubos

Posted in May 6, 2008 by 211.30.186.96

> I'm not Java programmer myself and never worked with Prevayler but Baptism problem could be solved.
> Of course Prevayler would need to use its own serialization code that would detect any objects that are already
> persisted by Prevayler and just serialize them as simple lookup ID instead of whole object tree as standard JAVA
> serialization does I guess.

It's actually quite easy to handle references to business object by customizing writeReplace () / readResolve () within the standard serialization framework. The real pain with this approach is that you have to manage a * huge * weak map relating business objects to persistence IDs: the details get quickly gory and so possibly memory usage … on the other hand, that sort of central object index * could * be put to good use in system wide queries.

- - Ale

Posted in Aug 4, 2008 by 87.5.166.11