From the JPA 2.0 specification section 3.3.2:
For both transaction-scoped and extended persistence contexts, transaction rollback causes all pre-existing managed instances and removed instances to become detached. The instances’ state will be the state of the instances at the point at which the transaction was rolled back. 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.
It is expected that a transaction rollback will cause the managed objects (associated with the extended persistence context) to be detached.
Also note more details about this in JPA specification section 7.9.2
The Provider has no knowledge of the distinction between transaction-scoped and extended persistence contexts. It provides entity managers to the container when requested and registers for transaction synchronization notifications.
... skipping other details
* When the JTA transaction rolls back, the provider must detach all managed entities.
Have you tried merging the detached entities back in? That is one way to restablish the application state after a transaction rollback.
Thanks Scott, it's really good to know that this is expected behaviour and something that needs to be dealt with. It sounds like the best approach is to minimise the number of exceptions that are allowed to cross the service boundary in order to prevent unnecessary detachments, combined with the @ApplicationException annotation that James mentions in your linked post, where appropriate.
Is there a way to know if an entity is detached, other than to try and persist it? So, for example if I have three service calls:
1. Reads information into persistent context + creates a new entity
2. Tries to create a new entity, referencing an existing one but this fails (resulting in everything becoming detached0
3. Tries to create a new entity, referencing an existing one, which would succeed however the dependent entity is detached.
From what you've said, the entities in the context are detached during the rollback of the second call. Do I need to store information as a result of the rollback so that when the third call comes in I know that I need to reread / merge the entities, or is this information somehow available through the entity manager? In other words, given an entity and an entity manager is there a way to tell if the entity manager is currently managing the entity, or if the entity has become detached (as a result of a previous issue)? Or would you suggest calling merge rather than persist when creating entities that have dependencies on existing (possibly detached) entities from the extended persistence context?