I put this on the users group recently to complete a thread, it belongs here 
really I suppose.

The problem manifests when multiple PUs are defined in persistence.xml and then 
referred to in classes using the @PersistenceContext(unitName= annotation. As 
it is in 5.3.6 the first EntityManager wired up gets injected to all successive 
EntityManager instances and the unitName= value is ignored. Probem was caused 
by reusing a class variable.

Also refactored to use PlasticProxyFactory.

John


----- Original Message ----- 
From: John 
To: Tapestry users 
Sent: Tuesday, November 13, 2012 7:51 AM
Subject: PATCH: tapestry-jpa EntityManagerObjectProvider fixes entities not 
associated with correct entity manager issue


This looks like a bug where a class member variable is used to cache the 
EntityManager that is subsequently handed to all the PersistenceContext 
annotations regardless of the unitName, like I said.

The following replacement class is tested working and handles multiple 
persistence units correctly as per the original Tapestry docs, just put it on 
your classpath first. Maybe someone on the developer side can check this out 
and commit it to the build cycle.


package org.apache.tapestry5.internal.jpa;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.apache.tapestry5.ioc.AnnotationProvider;
import org.apache.tapestry5.ioc.ObjectCreator;
import org.apache.tapestry5.ioc.ObjectLocator;
import org.apache.tapestry5.ioc.ObjectProvider;
import org.apache.tapestry5.ioc.services.PlasticProxyFactory;
import org.apache.tapestry5.jpa.EntityManagerManager;

/**
 * A patched version to use PlasticProxyFactory and not cache the EntityManager 
as a class member.
 * @author John Coleman
 */
public class EntityManagerObjectProvider implements ObjectProvider
{

    /**
     * {@inheritDoc}
     */
    public <T> T provide(final Class<T> objectType, final AnnotationProvider 
annotationProvider,
            final ObjectLocator locator)
    {
        if (objectType.equals(EntityManager.class))
            return objectType.cast(getOrCreateProxy(annotationProvider, 
locator));

        return null;
    }

    private synchronized EntityManager getOrCreateProxy(
            final AnnotationProvider annotationProvider, final ObjectLocator 
objectLocator)
    {
            final PlasticProxyFactory proxyFactory = 
objectLocator.getService("PlasticProxyFactory",
              PlasticProxyFactory.class);

             final PersistenceContext annotation = annotationProvider
                            .getAnnotation(PersistenceContext.class);

            EntityManager proxy = proxyFactory.createProxy(EntityManager.class, 
new ObjectCreator<EntityManager>()
            {
                public EntityManager createObject()
                {
                    final EntityManagerManager entityManagerManager = 
objectLocator
                            .getService(EntityManagerManager.class);

                    return 
JpaInternalUtils.getEntityManager(entityManagerManager, annotation);
                }
            }, "<EntityManagerProxy>");

        return proxy;
    }

}

Reply via email to