JPA Transitive Persistence for the Play Framework

In play framework 1.x the JPA persistency model has been changed in a dramatic way. JPA as a standard is all about transitive persistence. That means, within a JPA transaction, any change to any object that is managed by the EntityManager will result in propagation of these changes into the database, that means the transitive hull of the loaded reachable object graph is traversed (considering Cascade annotation), then compared to the loaded state and then the full delta is committed to the DB. It is all happening implicitly. The easiness of this automatism is an achievement which took the Java Enterprise world quite some time.

Play now, on the other hand, tries to resemble the logic found in web frameworks like Ruby on Rails, where the save operation is an explicit operation. You will need to call save on any object whose changes you want to propagate to the database. Play has implemented a cascade when the corresponding JPA annotation is present so you don’t need to call save() on all of them but even this solution is not complete, which I wrote about in Beware of this: play framework’s cascaded save() only works on loaded collections.

To be honest, I don’t like play’s (or RoR’s) approach. The logic behind it is, that you can make changes to as many objects you want and if an error occurs somewhere down the logic, you will not need to undo the changes that you made before the error occurred. The same can be accomplished by just not committing the running JPA transaction (i.e., rolling it back). In a J2EE environment, you just don’t want to control the transactions yourself. The JPA hack in play makes it necessary to do exactly that. If you are in a non-trivial environment, where you need to manage more complex object models you don’t want to mess up with the transaction which demarcates the unit of work! Some logic might apply changes which result in changes in the reachable object graph. The programmer of that logic doesn’t necessarily need to know that perhaps the initial change will ripple through to other objects. We call that encapsulation, and that is broken by play’s approach.

Long story short, in order to circumvent that, I created a module that brings the original JPA behavior of transitive persistence back to play. The API is exactly the same as in original play with the exception that it is necessary to inherit the model classes from a different base class. Instead of calling save on every changed object it is only necessay to call persist() on newly created objects. Every other change is handled by the transitive persistence logic of JPA just as it was originally intended.

The module is not publicly available, but I’ve been using it successfully in all my play projects. I just wanted to let you know about it and of course will I make it available (in github) if people ask for it. So, if you want the real JPA back in play, drop me a note and I will publish it.