Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add @RequestScoped EntityManager Example #238

Open
codylerum opened this issue Jul 14, 2014 · 10 comments
Open

Add @RequestScoped EntityManager Example #238

codylerum opened this issue Jul 14, 2014 · 10 comments

Comments

@codylerum
Copy link

A very common pattern is to use an EntityManager which is @RequestScoped with CDI. This is often referred to as the entitymanager-per-request pattern.

Currently I am unable to make this work in coordination with @Transactional without going SynchronizationType.UNSYNCHRONIZED and manually calling an entityManager.joinTransaction()

public class PersistenceResources {

    @PersistenceContext(type = PersistenceContextType.EXTENDED, synchronization = SynchronizationType.SYNCHRONIZED)
    private EntityManager em;

    @Produces
    @RequestScoped
    private EntityManager requestScopedEntityManager() {
        return em;
    }
}

Unfortunately all the entities appear to get detached after the first transaction commits. Is this pattern possible with EE 7 without having to manually join to the transaction?

@codylerum
Copy link
Author

This was done in DeltaSpike with an @PersistenceUnit EntityManagerFactory but that utilized its own Transactions module to handle the synchronization of the EntityManager to the Transaction. See - https://deltaspike.apache.org/jpa.html

@codylerum
Copy link
Author

@arun-gupta I have an example here https://github.com/codylerum/eebox/tree/requestscoped_em that shows the issue. (use the requestscoped_em branch)

There is an link to both the working and the broken from the context root /eebox (tested on wildfly 8.1.0.Final)

What appears to be happening is that the enitymanager only joins the first transaction it is envolved in even though there may be multiple during the request.

Can you deploy this and see if you are seeing the same? From what I understand it shouldn't be behaving like this. If you see the same maybe you can check with the jpa+tx experts on your side to see why and if it is an issue or working as designed.

@arun-gupta
Copy link
Contributor

thanks for detailed explanation, I've asked some folks to look at it.

@codylerum
Copy link
Author

@arun-gupta Thanks. Let me know if there is anything else I can do to move this along.

@codylerum
Copy link
Author

@arun-gupta Arun FWIW this does appear to have the same behavior with Glassfish as it does with wildfly.

@scottmarlow
Copy link

PersistenceContextType.EXTENDED only works with EJB stateful session beans. What happens if you use transaction scoped persistence context instead?

@PersistenceContext
private EntityManager em;

We have pretty good TRACE logging in WildFly that helps illustrate what is happening. Enable trace logging (http://|https//docs.jboss.org/author/display/WFLY9/JPA+Reference+Guide#JPAReferenceGuide-Troubleshooting) for org.jboss.jca, org.hibernate, org.jboss.as.jpa and com.arjuna to get more information about what is occurring exactly (from tx start to tx end).

@codylerum
Copy link
Author

@scottmarlow The EM detaches everything after the first tx completes.

If I use

@PersistenceUnit
private EntityManagerFactory entityManagerFactory;

@Produces
@RequestScoped
public EntityManager entityManager() {
   log.infof("Producing Entity Manager");
   return entityManagerFactory
    .createEntityManager(SynchronizationType.SYNCHRONIZED);
}

The EntityManager stays alive but it will not automatically join another transaction. It will join a first and I can manually join it to others with an EntityManager#joinTranscation() I don't know if this is a bug or just something that was thought of with regards to TX and EntityManager in EE 7

@scottmarlow
Copy link

From JPA 2.1 specification:
"7.7 Application-managed Persistence Contexts

When an application-managed entity manager is used, the application interacts directly with the persistence provider's entity manager factory to manage the entity manager lifecycle and to obtain and destroy persistence contexts.

All such actions application-managed persistence contexts are extended in scope, and can span multiple transactions.

The EntityManagerFactory.createEntityManager method and the EntityManager close and isOpen methods are used to manage the lifecycle of an application-managed entity manager and its associated persistence context.

The extended persistence context exists from the point at which the entity manager has been created using EntityManagerFactory.createEntityManager until the entity manager is closed by means of EntityManager.close.

An extended persistence context obtained from the application-managed entity manager is a standalone persistence context—it is not propagated with the transaction.

When a JTA application-managed entity manager is used, an application-managed persistence context may be specified to be of type SynchronizationType.UNSYNCHRONIZED. A persistence context of type SynchronizationType.UNSYNCHRONIZED is not enlisted in any JTA transaction unless explicitly joined to that transaction by the application. A persistence context of type Synchro-
nizationType.UNSYNCHRONIZED is enlisted in a JTA transaction and registered for subsequent
transaction notifications against that transaction by the invocation of the EntityManager joinTransaction method. The persistence context remains joined to the transaction until the transaction commits or rolls back. After the transaction commits or rolls back, the persistence context will not be joined to any subsequent transaction unless the joinTransaction method is invoked in the scope of that subsequent transaction.

When a JTA application-managed entity manager is used, if the entity manager is created outside the scope of the current JTA transaction, it is the responsibility of the application to join the entity manager to the transaction (if desired) by calling EntityManager.joinTransaction. If the entity manager is created outside the scope of a JTA transaction, it is not joined to the transaction unless EntityManager.joinTransaction is called.

The EntityManager.close method closes an entity manager to release its persistence context and other resources. After calling close, the application must not invoke any further methods on the EntityManager instance except for getTransaction and isOpen, or the IllegalStateException will be thrown. If the close method is invoked when a transaction is active, the persistence context remains managed until the transaction completes.

The EntityManager.isOpen method indicates whether the entity manager is open. The isOpen method returns true until the entity manager has been closed.
"

I included the enter section for completeness but really just want to point out the seventh paragraph which I will repeat again here so everyone can avoid reading the entire above text if they like :)

"
When a JTA application-managed entity manager is used, if the entity manager is created outside the scope of the current JTA transaction, it is the responsibility of the application to join the entity manager to the transaction (if desired) by calling EntityManager.joinTransaction. If the entity manager is created outside the scope of a JTA transaction, it is not joined to the transaction unless EntityManager.joinTransaction is called.
"

Sounds like you are seeing that the application-managed entity manager, is not auto-joining any subsequent JTA transaction, which is correct as per the above paragraph.

@codylerum
Copy link
Author

@scottmarlow OK. That sounds like this is correct behavior then according to spec and it would just require manual joining. Thanks!

@jwgmeligmeyling
Copy link

I'd love to see an example still. So what was the conclusion of this topic? Is the producer code still valid? Where does joinTransaction() come in to play?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants