David Van Couvering: JPA and Rollbacks - Not Pretty


News: David Van Couvering: JPA and Rollbacks - Not Pretty

  1. David Van Couvering has posted "JPA and Rollbacks - Not Pretty," discussing how the Java Persistence Architecture manages rollback conditions... "JPA rollback is like a tornado that sweeps through your JPA house and now everything is twisted and ruined, and you have to try and clean it all up." The relevant bit from the spec:
    3.3.2 Transaction Rollback For both transaction-scoped and extended persistence contexts, transaction rollback causes all pre-existing managed instances and removed instances to become detached. ... Transaction rollback typically causes the persistence context to be in an inconsistent state at the point of rollback. In particular, the state of version attributes and generated state (e.g., generated primary keys) may be inconsistent. Instances that were formerly managed by the persistence context (including new instances that were made persistent in that transaction) may therefore not be reusable in the same manner as other detached objects—for example, they may fail when passed to the merge operation.
    Ecmel Ercan posted a design pattern to the Glassfish persistence mailing list that basically detaches all objects from an EntityManager as soon as the transaction ends, which has costs of its own:
    Every time you merge there is a full copy from your detached object to a separate managed object. Depending on the number of objects you are managing, this can get expensive. Also, JPA says you can not rely on attributes of your object being available in a detached object if you are using lazy loading. The default behavior of JPA is eager loading, but for large object graphs you may want to do lazy loading. But that is not really feasible in any portable way when you use this design pattern. All I can say is that this may be the cost of having any kind of guarantee that you are working with data that is consistent and reliable.
    David finishes up by saying that the spec group is aware of it, and they're hoping to resolve it better in the next version of the specification.
  2. Does detaching objects help?[ Go to top ]

    Object graph is the state. If you have anyway modified the object graph, there is no way to go back - detached or managed (unless you have cloned the entire object graph). This is as good as discarding the current entitymanager and starting over with the new one. I think, JPA has to restore back the managed objects to the older state. It is also crucial for nested transaction support. mani
  3. JDO can help here[ Go to top ]

    Note: I also responded with the same comment on David's blog. JDO has sophisticated rollback handling capabilities, including options to configure whether objects are detached upon commit (see option javax.jdo.option.DetachAllOnCommit), and whether values are to be restored to what they were at the beginning of the transaction (see option javax.jdo.option.RestoreValues). Exceptions thrown during rollback also include the failed objects, so that you can more intelligently handle the exceptions. Further, some exceptions indicate conditions that can't be retried (derived from javax.jdo.JDOFatalException) versus those that can be retried (javax.jdo.JDOCanRetryException). Also, JDO supports but does not require that your objects have a field (or fields) to be used for optimistic consistency checks (or identity, for that matter). With regard to fetching, JDO supports flexible fetch plans (javax.jdo.FetchPlan) by combining fetch groups together additively. This allows you to precisely define the boundary of the object graph to be detached. Any field that you try to access once an object is detached throws javax.jdo.JDODetachedFieldAccessException. In addition to these options, you'll find reasonable defaults for most of this behavior in JDO.
  4. Re: JDO can help here[ Go to top ]

    Great. Looks like it would be easy for JDO to support savepoints (for undo operations) and perhaps some sophisticated features such as change summary (like in SDO) per operation/request not per conversation. This can be helpful in incremental UI updates and reduce serialization overhead. But JPA is here to stay and has lots of vendor support. So people like us have already made the choice to go with JPA. And now, i am not sure how they will solve this problem unless they introduce the complexities they are up against like the field interception, transient transactional etc.
  5. First, just to make sure there is no confusion, the "ruin" spoken of, exists only in memory. The transactional integrity of the data in the database is intact. Furthermore, the "wreckage" of detached objects doesn't need to be cleaned up. There is a garbage collector, and it cleans up everything we're willing to ignore. The current JPA behavior covers, IMO, 80% or more of the use cases. When the OptimisticLockException occurs, most applications do not know enough to recover without going back to the user. Generally, the recovery logic is to tell the user "Sorry someone else change the information that you were editing, try again". Often users don't mind this -- it lets them know they are connected to a real-time system. In other cases, the application is executing a command and has all the information that it needs to repeat the work on fresh objects. Any fix to the current JPA behavior will have to be deep. For example, simply preserving unchanged the detached or managed objects (as they existed prior to the attach or commit failure) won't do much good as they will still have stale version values. Refreshing an object to get an up to date version values would also blow away the changes that the user made. So, if work really should be done on this "problem", and I'm not sure that it should, we need compelling and detailed use cases, where a different behavior by JPA would make the application simpler without sacrificing the simplicity of JPA.
  6. David, Here are the use cases: 1) Undo operations/Savepoints with JPA: Let's take the case of a long running conversation where several operations (as individual web requests) have been carried out by the user to reach a particular object state (and not yet commited to the database). From here, if i want to undo the changes that i made during the last operation alone, i have no way of doing it with JPA. I guess JDO also does not support this at this point in time. But my understanding is that, JDO has more likely hood to support this because it tracks changes possibly with field interceptors (and could stack these changes as savepoints). 2) Incremental UI updates in AJAX with rich client state: AJAX applications with rich client state needs only the incremental changes that happened during the request (and not between save/commit). Otherwise we will end up sending the entire (or relevant subset) object tree to the UI everytime. This is inefficient and also requires the AJAX applications to render the whole UI (making it merely a client side html renderer). Again this is not supported in JDO as well, but could be matter of exposing the savepoint changes. JPA is great in a lot of aspects and of course is simple. But end of the day, when the customer asks for an undo feature, i can't say that JPA made his life miserable, to make mine simpler. mani
  7. Hi Mani, Use case: undo operations and support for savepoints If there were no database, and no JPA implementation involved in the application, and the customer requests an "undo" operation, where would you be then? You'd have to roll your own. In a rich client application, detached objects can be used to back the dialog box and when the user says "OK" to exist the dialog box, the changes made can be applied to the persistence context. If the user want to undo after saving his changes in the dialog box, it would not be unreasonable to ask him to start over. Nonetheless, many databases do support savepoints, and it seems reasonable to ask JPA (and JDO) implementations to support this feature. It might not be easy for them, but it's reasonable. Then application developers could use robust support for savepoints in JPA to implement an undo feature in their applications. Use case: incremental updates for AJAX clients I don't think much progress will be made here until there is some kind of standard for representing the incremental changes. Is there already such a thing? Cheers, David
  8. David, Doing undo stack in the application is definitely messy (and buggy). Object graph foot print in web apps make it worse. I am sure frameworks will do a much better job. So I hope the expert committee does something to address this need.
    I don't think much progress will be made here until there is some kind of standard for representing the incremental changes. Is there already such a thing?
    I felt SDO would be perfect fit here. If i am right there was a javascript implementation for SDO from IBM already. thanks, mani
  9. SDO, which started as JSR 235, finished last fall at OSOA, http://osoa.org/display/Main/Service+Data+Objects+Home
  10. I am trying solution[ Go to top ]

    What about to keep one EntityManager for transactions which never end by rollback and it will always keep objects manageable. And for transactions which can be rollbacked we always create new EntityManager? It seems that new EM sees objects from first EM as detachable, but it's not as bad, I can include them in querys without problem.