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. The bug makes it seem that entities are not wired to the EntityManager as you would expect, in fact the reference passed in is bad.

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

}

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@tapestry.apache.org
For additional commands, e-mail: dev-h...@tapestry.apache.org

Reply via email to