In our J2EE application, we use a EJB-3 stateful bean to allow the front code to create, modify and save persistent entities (managed through JPA-2).
It looks something
If you use extended persistence context all operations on managed entities done inside non-transactional methods are queued to be written to the database. Once you call flush() on entity manager within a transaction context all queued changes are written to the database. So in other words, the fact that you have a transactional method doesn't commit the changes itself when method exits (as in CMT), but flushing entity manager actually does. You can find full explanation of this process here
Because there is no way to know "when" the client is done with the session (extended scope).
To be direct and to the metal, there will be no javax.transaction.Synchronization
objects registered for the EntityManager in question until you actually use it in a transaction.
We in app-server-land will create one of these objects to do the flush()
and register it with the javax.transaction.TransactionSynchronizationRegistry
or javax.transaction.Transaction
. This can't be done unless there is an active transaction.
That's the long and short of it.
Yes, an app server could very well keep a list of resources it gave the stateful bean and auto-enroll them in every transaction that stateful bean might start or participate in. The downside of that is you completely lose the ability to decide which things go in which transactions. Maybe you have a 2 or 3 different transactions to run on different persistence units and are aggregating the work up in your Extended persistence context for a very specific transaction. It's really a design issue and the app server should leave such decisions to the app itself.
You use it in a transaction and we'll enroll it in the transaction. That's the basic contract.
Side note, depending on how the underlying EntityManager is handled, any persistent call to the EntityManager may be enough to cause a complete flush at the end of the transaction. Certainly, flush()
is the most direct and clear but a persist()
or even a find()
might do it.