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;
}
}