persistence@glassfish.java.net

RE: EntityManagerFactory.getEntityManager() and pctx propagation

From: Mike Keith <michael.keith_at_oracle.com>
Date: Wed, 21 Dec 2005 17:14:48 -0500

> -----Original Message-----
> From: Sanjeeb.Sahoo_at_Sun.COM [mailto:Sanjeeb.Sahoo_at_Sun.COM]On Behalf Of
> Sanjeeb Kumar Sahoo
> Sent: Wednesday, December 21, 2005 1:28 PM
> To: Mike Keith
> Cc: persistence_at_glassfish.dev.java.net; Kenneth Saks
> Subject: EntityManagerFactory.getEntityManager() and pctx propagation
>
>
> Hi Mike, Gordon,
>
> What is the rational behind allowing EMF.getEntityManager()
> to return an
> EntityManager even though there is no active JTA transaction?
>

getEntityManager returns the Container-Managed EntityManager, and should act the
same as an injected CM EM. It should be same as doing:

@PersistenceContext EntityManager em;
@Resource UserTransaction utx;

// Not part of the pc since there is no pc yet.
UserCredential credential = em.find(UserCredential.class, name);

utx.begin();
...

> In my code, if I do the following, what is the expected behavior:
>
> EntityManager em = emf.getEntityManager();
>
> UserCredential credential =
> em.find(UserCredential.class, name);
> credential.setPassword("newpassword");
>
> utx.begin();
>
> EntityManager em2 = emf.getEntityManager();
> // Should em and em2 share the same
> PersistenceContext? I am
> currently observing different behavior in glassfish.
>

If it is not an "extended" pc then there is no pc until the transaction starts.
If the pc is "extended" (an extended one was already in scope) then they should be the same pc.

> UserCredential credential2 =
> em2.find(UserCredential.class,
> name);
> // I am expecting to see changed password in credential2,
> but I don't see this.

Again, it depends on whether the pc is extended or not. If it was then
it should be the case that credential2 == credential.

>
> If I begin the transaction first and then subsequent EntityManagers
> returned by getEntityManager() share the same persistence context. But
> in my code, I first called getEntityManager(), then
> utx.begin() and then
> again getEntityManager(). So I am not sure, what I am
> observing is a bug
> or indeed the correct behavior. If this is the correct
> behavior, do you
> think average programmers will understand these subtle differences?
>

If this was a tx-scoped EM then what you are seeing is correct behaviour.
If it is an xpc then it makes no difference whether a tx is started or not, the
pc should be shared within the same EJB invocation.

> The javadoc for getEntityManager() says the following:
> /**
> * Get an EntityManager instance whose persistence context
> * is propagated with the current JTA transaction.
> * If there is no persistence context bound to the current
> * JTA transaction, a new transaction-scoped persistence
> * context is created and associated with the transaction
> * and the entity manager instance that is created and
> * returned. If no JTA transaction is in progress, an
> * EntityManager instance is created for which the persistence
> * context will be propagated with subsequent JTA transactions.
> * Throws IllegalStateException if called on an
> * EntityManagerFactory that does not provide JTA EntityManagers.
> */
> EntityManager getEntityManager();
>

The highlighted area might be the confusing bit. It kind of implies that
a pc is created and then propagated into the next tx, but if a tx-scoped pc
then no pc exists until the next tx. This should be worded better.

>
> Thanks,
> Sahoo
>
>
>