Page 1 of 2 12 LastLast
Results 1 to 10 of 12

Thread: Injection of PersistenceContext with PersistenceContextType EXTENDED

  1. #1
    Join Date
    May 2006
    Location
    Germany
    Posts
    49

    Default Injection of PersistenceContext with PersistenceContextType EXTENDED

    Hello everybody,

    I'm currently looking at the new JPA Support of Spring 2.0 and also would like to know, how an Entity Manager injected via @PersitenceContext works, if you use PersistenceContextType EXTENDED. (See http://forum.springframework.org/showthread.php?t=27209)

    As far as I understand, it's an container managed Entity Manager with the semantic of JPA extended entity manager.
    My main problem with this Entity Manager: how closes it? It's not closed when a tx ends because it's an extended entity manager. On the other hand it can't be closed by the application, because it's a container managed entity manager.

    Does it make sense to use PersistenceContextType EXTENDED in a purly Spring managed environment?

    Any feedback is very welcome.

    Regards
    Stefan

  2. #2
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    Yes it does - Extended context means that you have to take care of the transaction and the entity manager closing. While for most cases this is undesirable, such functionality makes sense in a detached environment when you might want the entity manager to live through out several requests (for example to associate a entity manager with a wizard that spans across several pages).
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  3. #3
    Join Date
    May 2006
    Location
    Germany
    Posts
    49

    Default

    Hello Costin,

    thank you for your quick reply. I would also say that an extended, application managed entity manager can make sence in some use cases. But one more, a bit more specific question: What happen's, if I try to use a "container managed" entity manager with Type "EXTENDED", thus injecting the entity manager with an Annotation "@PersistenceContext(..., type=PersistenceContextType.EXTENDED)". What will happen then?

    Regards
    Stefan

  4. #4
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    The container will create the entity manager for you but that's about it. You'll have to start/commit the transaction yourself as well as close the entity manager.
    You can replace extended with manual - it's the non-managed type of behavior.

    Below you have some code taken from the OpenJPA documentation (I think you can find examples and more explanations in the docs from other JPA providers):
    EntityManagerFactory emf = ...
    EntityManager em = emf.createEntityManager (PersistenceContextType.EXTENDED);

    // persistence context active for entire life of EM, so only one entity
    // for a given persistent identity
    Magazine mag1 = em.find (Magazine.class, magId);
    Magazine mag2 = em.find (Magazine.class, magId);
    assertTrue (mag2 == mag1);

    em.getTransaction ().begin ();

    // same persistence context active within the transaction
    Magazine mag3 = em.find (Magazine.class, magId);
    assertTrue (mag3 == mag1);
    Magazine mag4 = em.find (Magazine.class (magId);
    assertTrue (mag4 == mag1);

    em.getTransaction.commit ();

    // when the transaction commits, instance still managed
    Magazine mag5 = em.find (Magazine.class, magId);
    assertTrue (mag5 == mag1);

    // instance finally becomes detached when EM closes
    em.close ();
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  5. #5
    Join Date
    Jul 2006
    Location
    Germany, Hamburg
    Posts
    8

    Default

    Dear Costin,

    in general, using an Extended Persistence Context makes sense, both on a typical rich client application in an architectural style like the one called "long running session" with hibernate or in environment which stores attached entities over more than one request/response cycle.

    But what is the semantic and usage with Spring? In the current state of RC2 an PersistenceContext of typ EXTENDED is automatically created by Spring when injected by @PersistenceContext annotation and activated by the PersistenceAnnotationBeanPostProcessor. The semantic is a "container-managed Persistence Context", so application code is not able to close the PersistenceContext, because -as bezzlebug stated- the EPC is container-managed.

    From my current point of view I noticed a semantic mismatch between application-managed and container-managed from the Spring perspective. To make myself clear: this mismatch is well founded in terms of plain JPA running within an EJB 3 compliant Java EE container. What is the understanding of container-managed in Spring environments?

    Best regards

  6. #6
    Join Date
    Jan 2005
    Location
    Bucharest, Romania
    Posts
    5,403

    Default

    I've reviewed the spec and talked with Juergen and the situation is this:
    JPA has two types of EntityManagers - application-managed and container-managed.
    The container-managed are injected through annotations (with regard to the PersistenceContextType) while for application-managed one gets a hold of the EntityManagerFactory (EMF) either through annotations or setter/constructor injection.
    For application-managed EM, one has to retrieve the EM from the EMF and then use it as shown in my previous post.
    Costin Leau
    SpringSource - http://www.SpringSource.com- Spring Training, Consulting, and Support - "From the Source"
    http://twitter.com/costinl
    Please use [ c o d e ] [ / c o d e ] tags

  7. #7
    Join Date
    May 2006
    Location
    Germany
    Posts
    49

    Default

    Hello Costin,

    it's me again. First of all thank you for the clarification. It's help's a lot in understanding the support for JPA that Spring has to offer. I really appreciate the the time you spend in answering all these questions!

    But one question still remains. It would be glad if you could help me on this too. The question is: Is there a szenario supported by Spring where you can use a container managed entity manager (injected by @PersistenceContext) with extended persistence context type without using a (stateful) EJB 3 session bean? If so, what kind of environment or context do you need to do this?

    So lets assume you run a Spring managed application in an non EJB enviroment, e.g. a web application in Tomcat.

    Lets assume you use LocalContainerEntityManagerFactoryBean to provide an JPA Entity Manager Factory and PersistenceAnnotationBeanPostProcessor to support the @PesistenceXxx-Annotations.

    Lets assume you have a DAO-Implementation using JPA, and you inject a JPA Entity Manager like this:

    Code:
    public class MyDaoPlainJpaImpl implements MyDaoInterface {
    
        @PersistenceContext(type = PersistenceContextType.EXTENDED)
        private EntityManager em;
    
        ....
    }
    Then PersistenceAnnotationBeanPostProcessor provides the Entity Manager with this method call:

    Code:
    ExtendedEntityManagerCreator.createContainerManagedEntityManager(emf)
    which returns a proxy for the native Entity Manager provided by the Entity Manager Factory that's configured by LocalContainerEntityManagerFactoryBean.

    The invocation handler for this proxy handles a call for the method "close" like this:

    Code:
    ...
    else if (method.getName().equals("close")) {
    	if (this.containerManaged) {
    		throw new IllegalStateException("Invalid usage: Cannot close a container-managed EntityManager");
    	}
    }
    ...
    So you can not close the entity manager by yourself. That's ok, because it's a container managed entity manager.

    But on the other hand, the Transaction Synchronization Adapter, (ContainerManagedExtendedEntityManagerSynchronizat ion) provided by ExtendedEntityManagerCreator for an extended Entity Manager does not close the entity manager either:

    Code:
    ...
    public void afterCompletion(int status) {
    			this.entityManagerHolder.setSynchronizedWithTransaction(false);
    	if (status != TransactionSynchronization.STATUS_COMMITTED) {
    		this.entityManagerHolder.getEntityManager().getTransaction().rollback();
    	}
    	else {
    		this.entityManagerHolder.getEntityManager().getTransaction().commit();
    	}
    	// Don't close the EntityManager...that's up to the user
    }
    ...
    This is correct, because it's an extended entity manager.

    But the problem is that in this scenario, the entity manager isn't closed after completion of a transaction (because it's extended) and you can't close the entity manager by yourself (because it's container managed).

    So my question: Is it actually meaningfull to use "@PersistenceContext(type = PersistenceContextType.EXTENDED)" in this scenario? Or can you only use this together with a statful EJB session bean? Is there any scenario without statful EJB session beans where you can use "@PersistenceContext(type = PersistenceContextType.EXTENDED)"? (Probably with the new Feature off HTTP Session scoped Spring Beans, provided by Spring 2.0?) Or do you have to use application managed entity manager, if you need to use an extended one. (And then use it like you discribed before.)

    Regards
    Stefan

  8. #8
    Join Date
    Aug 2007
    Posts
    1

    Default

    I realize this is an old topic, but Stefan's question remains unanswered, What closes a container managed extended persistence context in the Spring environment?

    In an EJB environment, the persistence context is closed by the container when the @Remove method of the stateful session bean completes (or the stateful session bean instance is otherwise destroyed). How does it work in Spring?

  9. #9

    Default

    I am using @PersistenceContext to inject an instance of EntityManager in my DAO classes. I ran into this scenario -

    I was trying to persist a Person entity from a PersonDAO class method like

    Code:
    @Transactional
    public void save(Person transientInstance) {
    		
    		try {           
                entityManager.persist(transientInstance);
                entityManager.flush();		
    		} catch (Exception e) {
    		
    			throw e;
    		}
    	}

    and have also configured a Hibernate Interceptor to perform audits on the Person entity. From within the interceptor I invoke AuditDAO method to fetch audit related data like

    Code:
        public Audit findAudit(String applicationName,
                String entityName) {
    
            log.info("Finding auditable entity with application name "
                    + applicationName + "key " + entityName);
            Audit entity = null;
            String queryString = "from Audit model where model."
                    + APPLICATION + "= :applicationValue and " + KEY
                    + "= :keyValue";
            try {
                
                Query query = entityManager.createQuery(queryString);
                query.setParameter("applicationValue", applicationName);
                query.setParameter("keyValue", entityName);
                entity = (Audit) query.getSingleResult();
            } catch (Exception e) {
               
                throw new AuditException (e);
            }
    
            if (entity != null) {        
                log.info("Audit found for applcation name "
                        + applicationName + "entity " + entityName);
    
            }
            
            return entity;
        }
    Both these DAO classes use

    Code:
    @PersistenceContext
        private EntityManager entityManager = null;
    Upon executing the code, I ran into following issues -
    1. The AuditDAO was not able to fetch records even though it existed in the db.
    2. The database identity for the Person class was not maintained.

    Upon adding the attribute PersistenceContextType.EXTENDED to @PersistenceContext annotation. The problem was resolved.

    I read in one of the articles that -

    By default JPA provide Transaction level Persistence Context. What this means is that the Persistence Context 'lives' for the length of the transaction. If you have multiple queries using the same transaction then the same Persistence Context is used for all of those queries.
    JPA provides 'Extended Persistence Context'. This could be thought of as the Persistence Context being 'owned' by the EntityManager rather than the Transaction. In this case the same Persistence Context can be used for multiple transactions.
    My questions are -

    Why did I get that error? Why was the transaction not maintained between calls across the interceptor? Does this scenario require PersistenceContextType.EXTENDED to be specified?

  10. #10

    Question so????

    Hello people,

    I'm new on this forum and on Spring as well.

    But like kott said, this question that beezlebug asked is good and remains unanswered. Does Costin Leau, Hammerstein, or anyone could give us a light??? I'm very curious about that...

    I know that this is a really old post, but maybe someone can teach me and all the others that come by here... Spring is now on 3.1, and maybe a lot of things has changed too ...

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •