You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ti...@apache.org on 2010/12/15 17:57:30 UTC

svn commit: r1049643 - in /incubator/aries/trunk/jpa: ./ jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/ jpa-container-itest/ jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/ jpa-conta...

Author: timothyjward
Date: Wed Dec 15 16:57:29 2010
New Revision: 1049643

URL: http://svn.apache.org/viewvc?rev=1049643&view=rev
Log:
ARIES-451 : Correctly purge the cache for non-transactional EntityManager access

Modified:
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAEntityManager.java
    incubator/aries/trunk/jpa/jpa-container-itest/pom.xml
    incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java
    incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java
    incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml
    incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml
    incubator/aries/trunk/jpa/pom.xml

Modified: incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAEntityManager.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAEntityManager.java?rev=1049643&r1=1049642&r2=1049643&view=diff
==============================================================================
--- incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAEntityManager.java (original)
+++ incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAEntityManager.java Wed Dec 15 16:57:29 2010
@@ -134,38 +134,80 @@ public class JTAEntityManager implements
 
   public boolean contains(Object arg0)
   {
-    return getPersistenceContext(false).contains(arg0);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.contains(arg0);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public Query createNamedQuery(String arg0)
   {
-    return getPersistenceContext(false).createNamedQuery(arg0);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.createNamedQuery(arg0);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public Query createNativeQuery(String arg0)
   {
-    return getPersistenceContext(false).createNativeQuery(arg0);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.createNativeQuery(arg0);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   @SuppressWarnings("unchecked")
   public Query createNativeQuery(String arg0, Class arg1)
   {
-    return getPersistenceContext(false).createNativeQuery(arg0, arg1);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.createNativeQuery(arg0, arg1);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public Query createNativeQuery(String arg0, String arg1)
   {
-    return getPersistenceContext(false).createNativeQuery(arg0, arg1);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.createNativeQuery(arg0, arg1);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public Query createQuery(String arg0)
   {
-    return getPersistenceContext(false).createQuery(arg0);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.createQuery(arg0);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public <T> T find(Class<T> arg0, Object arg1)
   {
-    return getPersistenceContext(false).find(arg0, arg1);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.find(arg0, arg1);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   /**
@@ -188,7 +230,13 @@ public class JTAEntityManager implements
 
   public <T> T getReference(Class<T> arg0, Object arg1)
   {
-    return getPersistenceContext(false).getReference(arg0, arg1);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.getReference(arg0, arg1);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public EntityTransaction getTransaction()
@@ -248,32 +296,66 @@ public class JTAEntityManager implements
 
   public void setFlushMode(FlushModeType arg0)
   {
-    getPersistenceContext(false).setFlushMode(arg0);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      em.setFlushMode(arg0);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public <T> TypedQuery<T> createNamedQuery(String arg0, Class<T> arg1)
   {
-    return getPersistenceContext(false).createNamedQuery(arg0, arg1);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.createNamedQuery(arg0, arg1);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public <T> TypedQuery<T> createQuery(CriteriaQuery<T> arg0)
   {
-    return getPersistenceContext(false).createQuery(arg0);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.createQuery(arg0);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public <T> TypedQuery<T> createQuery(String arg0, Class<T> arg1)
   {
-    return getPersistenceContext(false).createQuery(arg0, arg1);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.createQuery(arg0, arg1);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public void detach(Object arg0)
   {
-    getPersistenceContext(false).detach(arg0);
+    EntityManager em = getPersistenceContext(false);
+    //The detatched manager auto-detaches everything, so only
+    //detach from a "real" entity manager
+    if(em != detachedManager)
+      em.detach(arg0);
   }
 
   public <T> T find(Class<T> arg0, Object arg1, Map<String, Object> arg2)
   {
-    return getPersistenceContext(false).find(arg0, arg1, arg2);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.find(arg0, arg1, arg2);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   /**
@@ -281,7 +363,13 @@ public class JTAEntityManager implements
    */
   public <T> T find(Class<T> arg0, Object arg1, LockModeType arg2)
   {
-    return getPersistenceContext(arg2 != LockModeType.NONE).find(arg0, arg1, arg2);
+    EntityManager em = getPersistenceContext(arg2 != LockModeType.NONE);
+    try {
+      return em.find(arg0, arg1, arg2);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   /**
@@ -289,7 +377,13 @@ public class JTAEntityManager implements
    */
   public <T> T find(Class<T> arg0, Object arg1, LockModeType arg2, Map<String, Object> arg3)
   {
-    return getPersistenceContext(arg2 != LockModeType.NONE).find(arg0, arg1, arg2, arg3);
+    EntityManager em = getPersistenceContext(arg2 != LockModeType.NONE);
+    try {
+      return em.find(arg0, arg1, arg2, arg3);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public CriteriaBuilder getCriteriaBuilder()
@@ -354,11 +448,23 @@ public class JTAEntityManager implements
 
   public void setProperty(String arg0, Object arg1)
   {
-    getPersistenceContext(false).setProperty(arg0, arg1);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      em.setProperty(arg0, arg1);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 
   public <T> T unwrap(Class<T> arg0)
   {
-    return getPersistenceContext(false).unwrap(arg0);
+    EntityManager em = getPersistenceContext(false);
+    try {
+      return em.unwrap(arg0);
+    } finally {
+      if(em == detachedManager)
+        em.clear();
+    }
   }
 }

Modified: incubator/aries/trunk/jpa/jpa-container-itest/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jpa/jpa-container-itest/pom.xml?rev=1049643&r1=1049642&r2=1049643&view=diff
==============================================================================
--- incubator/aries/trunk/jpa/jpa-container-itest/pom.xml (original)
+++ incubator/aries/trunk/jpa/jpa-container-itest/pom.xml Wed Dec 15 16:57:29 2010
@@ -196,6 +196,11 @@
             <scope>test</scope>
         </dependency>
         <dependency>
+			<groupId>org.apache.aries.transaction</groupId>
+			<artifactId>org.apache.aries.transaction.wrappers</artifactId>
+            <scope>test</scope>
+		</dependency>
+        <dependency>
             <groupId>org.apache.aries.jndi</groupId>
             <artifactId>org.apache.aries.jndi.api</artifactId>
             <scope>test</scope>

Modified: incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java?rev=1049643&r1=1049642&r2=1049643&view=diff
==============================================================================
--- incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java (original)
+++ incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java Wed Dec 15 16:57:29 2010
@@ -15,11 +15,13 @@
  */
 package org.apache.aries.jpa.container.itest;
 
+import static org.ops4j.pax.exam.CoreOptions.bootDelegationPackages;
 import static org.ops4j.pax.exam.CoreOptions.equinox;
 import static org.ops4j.pax.exam.CoreOptions.options;
 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
 import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
 import static org.ops4j.pax.exam.OptionUtils.combine;
+import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption;
 
 import javax.persistence.EntityManagerFactory;
 
@@ -73,7 +75,8 @@ public class JPAContainerTest {
   @org.ops4j.pax.exam.junit.Configuration
   public static Option[] configuration() {
     Option[] options = options(
-        bootDelegation(),
+        bootDelegationPackages("javax.transaction", "javax.transaction.*"),
+        vmOption("-Dorg.osgi.framework.system.packages=javax.accessibility,javax.activation,javax.activity,javax.annotation,javax.annotation.processing,javax.crypto,javax.crypto.interfaces,javax.crypto.spec,javax.imageio,javax.imageio.event,javax.imageio.metadata,javax.imageio.plugins.bmp,javax.imageio.plugins.jpeg,javax.imageio.spi,javax.imageio.stream,javax.jws,javax.jws.soap,javax.lang.model,javax.lang.model.element,javax.lang.model.type,javax.lang.model.util,javax.management,javax.management.loading,javax.management.modelmbean,javax.management.monitor,javax.management.openmbean,javax.management.relation,javax.management.remote,javax.management.remote.rmi,javax.management.timer,javax.naming,javax.naming.directory,javax.naming.event,javax.naming.ldap,javax.naming.spi,javax.net,javax.net.ssl,javax.print,javax.print.attribute,javax.print.attribute.standard,javax.print.event,javax.rmi,javax.rmi.CORBA,javax.rmi.ssl,javax.script,javax.security.auth,javax.security.auth.callback,
 javax.security.auth.kerberos,javax.security.auth.login,javax.security.auth.spi,javax.security.auth.x500,javax.security.cert,javax.security.sasl,javax.sound.midi,javax.sound.midi.spi,javax.sound.sampled,javax.sound.sampled.spi,javax.sql,javax.sql.rowset,javax.sql.rowset.serial,javax.sql.rowset.spi,javax.swing,javax.swing.border,javax.swing.colorchooser,javax.swing.event,javax.swing.filechooser,javax.swing.plaf,javax.swing.plaf.basic,javax.swing.plaf.metal,javax.swing.plaf.multi,javax.swing.plaf.synth,javax.swing.table,javax.swing.text,javax.swing.text.html,javax.swing.text.html.parser,javax.swing.text.rtf,javax.swing.tree,javax.swing.undo,javax.tools,javax.xml,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.bind.util,javax.xml.crypto,javax.xml.crypto.dom,javax.xml.crypto.dsig,javax.xml.crypto.dsig.dom,javax.xml.crypto.dsig.keyinfo,javax.xml.crypto.dsig.spec,javax.xml.datatype,javax.xml.name
 space,javax.xml.parsers,javax.xml.soap,javax.xml.stream,javax.xml.stream.events,javax.xml.stream.util,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transform.stax,javax.xml.transform.stream,javax.xml.validation,javax.xml.ws,javax.xml.ws.handler,javax.xml.ws.handler.soap,javax.xml.ws.http,javax.xml.ws.soap,javax.xml.ws.spi,javax.xml.xpath,org.ietf.jgss,org.omg.CORBA,org.omg.CORBA.DynAnyPackage,org.omg.CORBA.ORBPackage,org.omg.CORBA.TypeCodePackage,org.omg.CORBA.portable,org.omg.CORBA_2_3,org.omg.CORBA_2_3.portable,org.omg.CosNaming,org.omg.CosNaming.NamingContextExtPackage,org.omg.CosNaming.NamingContextPackage,org.omg.Dynamic,org.omg.DynamicAny,org.omg.DynamicAny.DynAnyFactoryPackage,org.omg.DynamicAny.DynAnyPackage,org.omg.IOP,org.omg.IOP.CodecFactoryPackage,org.omg.IOP.CodecPackage,org.omg.Messaging,org.omg.PortableInterceptor,org.omg.PortableInterceptor.ORBInitInfoPackage,org.omg.PortableServer,org.omg.PortableServer.CurrentPackage,org.omg.
 PortableServer.POAManagerPackage,org.omg.PortableServer.POAPackage,org.omg.PortableServer.ServantLocatorPackage,org.omg.PortableServer.portable,org.omg.SendingContext,org.omg.stub.java.rmi,org.w3c.dom,org.w3c.dom.bootstrap,org.w3c.dom.css,org.w3c.dom.events,org.w3c.dom.html,org.w3c.dom.ls,org.w3c.dom.ranges,org.w3c.dom.stylesheets,org.w3c.dom.traversal,org.w3c.dom.views,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers,javax.transaction;partial=true;mandatory:=partial,javax.transaction.xa;partial=true;mandatory:=partial"),
         
         // Log
         mavenBundle("org.ops4j.pax.logging", "pax-logging-api"),
@@ -98,6 +101,8 @@ public class JPAContainerTest {
         mavenBundle("org.apache.aries.jndi", "org.apache.aries.jndi.url"),
         mavenBundle("org.apache.aries.jpa", "org.apache.aries.jpa.api"),
         mavenBundle("org.apache.aries.jpa", "org.apache.aries.jpa.container"),
+        mavenBundle("org.apache.aries.transaction", "org.apache.aries.transaction.manager" ),
+        mavenBundle("org.apache.aries.transaction", "org.apache.aries.transaction.wrappers" ),
         mavenBundle("org.apache.derby", "derby"),
         mavenBundle("org.apache.geronimo.specs", "geronimo-jta_1.1_spec"),
         mavenBundle("org.apache.geronimo.specs", "geronimo-jpa_2.0_spec"),

Modified: incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java?rev=1049643&r1=1049642&r2=1049643&view=diff
==============================================================================
--- incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java (original)
+++ incubator/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java Wed Dec 15 16:57:29 2010
@@ -17,20 +17,40 @@ package org.apache.aries.jpa.context.ite
 
 
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
+import static org.ops4j.pax.exam.CoreOptions.bootDelegationPackages;
 import static org.ops4j.pax.exam.CoreOptions.equinox;
 import static org.ops4j.pax.exam.CoreOptions.options;
 import static org.ops4j.pax.exam.CoreOptions.systemProperty;
 import static org.ops4j.pax.exam.CoreOptions.wrappedBundle;
 import static org.ops4j.pax.exam.OptionUtils.combine;
+import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.vmOption;
+import static org.ops4j.pax.exam.CoreOptions.waitForFrameworkStartup;
 
+import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Proxy;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
+import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
+import javax.persistence.FlushModeType;
+import javax.persistence.LockModeType;
 import javax.persistence.PersistenceContextType;
+import javax.persistence.Query;
+import javax.persistence.TransactionRequiredException;
+import javax.persistence.TypedQuery;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.transaction.UserTransaction;
 
 import org.apache.aries.jpa.container.PersistenceUnitConstants;
 import org.apache.aries.jpa.container.context.PersistenceContextProvider;
+import org.apache.aries.jpa.container.itest.entities.Car;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.ops4j.pax.exam.CoreOptions;
@@ -72,23 +92,327 @@ public class JPAContextTest {
       //Expected
     }
     
-    PersistenceContextProvider provider = getOsgiService(PersistenceContextProvider.class);
+    registerClient("test-unit");
     
-    HashMap<String, Object> props = new HashMap<String, Object>();
-    props.put(PersistenceContextProvider.PERSISTENCE_CONTEXT_TYPE, PersistenceContextType.TRANSACTION);
-    provider.registerContext("test-unit", bundleContext.getBundle(), props);
+    emf = getProxyEMF("test-unit");
+    
+  }
+
+  private EntityManagerFactory getProxyEMF(String name) {
     
-    emf = getOsgiService(EntityManagerFactory.class, "(&(osgi.unit.name=test-unit)(" 
+    return getOsgiService(EntityManagerFactory.class, "(&(osgi.unit.name=" + name + ")(" 
           + PersistenceUnitConstants.CONTAINER_MANAGED_PERSISTENCE_UNIT + "=true)" +
         "(" + PersistenceContextProvider.PROXY_FACTORY_EMF_ATTRIBUTE + "=*))", DEFAULT_TIMEOUT);
+  }
+  
+  @Test
+  public void testTranRequired() throws Exception {
+    registerClient("bp-test-unit");
+    
+    EntityManagerFactory emf = getProxyEMF("bp-test-unit");
+    
+    final EntityManager managedEm = emf.createEntityManager();
+    
+    ensureTREBehaviour(false, managedEm, "contains", new Object());
+    ensureTREBehaviour(false, managedEm, "createNamedQuery", "hi");
+    ensureTREBehaviour(false, managedEm, "createNativeQuery", "hi");
+    ensureTREBehaviour(false, managedEm, "createNativeQuery", "hi", Object.class);
+    ensureTREBehaviour(false, managedEm, "createNativeQuery", "hi", "hi");
+    ensureTREBehaviour(false, managedEm, "createQuery", "hi");
+    ensureTREBehaviour(false, managedEm, "find", Object.class, new Object());
+    ensureTREBehaviour(true, managedEm, "flush");
+    ensureTREBehaviour(false, managedEm, "getDelegate");
+    ensureTREBehaviour(false, managedEm, "getFlushMode");
+    ensureTREBehaviour(false, managedEm, "getReference", Object.class, new Object());
+    ensureTREBehaviour(true, managedEm, "lock", new Object(), LockModeType.NONE);
+    ensureTREBehaviour(true, managedEm, "merge", new Object());
+    ensureTREBehaviour(true, managedEm, "persist", new Object());
+    ensureTREBehaviour(true, managedEm, "refresh", new Object());
+    ensureTREBehaviour(true, managedEm, "remove", new Object());
+    ensureTREBehaviour(false, managedEm, "setFlushMode", FlushModeType.AUTO);
+    ensureTREBehaviour(false, managedEm, "createNamedQuery", "hi", Object.class);
+    ensureTREBehaviour(false, managedEm, "createQuery", Proxy.newProxyInstance(this.getClass().getClassLoader(),
+       new Class[] {CriteriaQuery.class}, new InvocationHandler() {
+      
+      public Object invoke(Object proxy, Method method, Object[] args)
+          throws Throwable {
+        return null;
+      }
+    }));
+    ensureTREBehaviour(false, managedEm, "createQuery", "hi", Object.class);
+    ensureTREBehaviour(false, managedEm, "detach", new Object());
+    ensureTREBehaviour(false, managedEm, "find", Object.class, new Object(), new HashMap());
+    ensureTREBehaviour(false, managedEm, "find", Object.class, new Object(), LockModeType.NONE);
+    ensureTREBehaviour(true, managedEm, "find", Object.class, new Object(), LockModeType.OPTIMISTIC);
+    ensureTREBehaviour(false, managedEm, "find", Object.class, new Object(), LockModeType.NONE, 
+        new HashMap());
+    ensureTREBehaviour(true, managedEm, "find", Object.class, new Object(), LockModeType.OPTIMISTIC, 
+        new HashMap());
+    ensureTREBehaviour(false, managedEm, "getCriteriaBuilder");
+    ensureTREBehaviour(true, managedEm, "getLockMode", new Object());
+    ensureTREBehaviour(false, managedEm, "getMetamodel");
+    ensureTREBehaviour(false, managedEm, "getProperties");
+    ensureTREBehaviour(true, managedEm, "lock", new Object(), LockModeType.NONE, new HashMap());
+    ensureTREBehaviour(true, managedEm, "refresh", new Object(), new HashMap());
+    ensureTREBehaviour(true, managedEm, "refresh", new Object(), LockModeType.NONE);
+    ensureTREBehaviour(true, managedEm, "refresh", new Object(), LockModeType.NONE, new HashMap());
+    ensureTREBehaviour(false, managedEm, "setProperty", "hi", new Object());
+    ensureTREBehaviour(false, managedEm, "unwrap", Object.class);
+
+    UserTransaction ut = getOsgiService(UserTransaction.class);
+    
+    ut.begin();
+    try{
+      ensureTREBehaviour(false, managedEm, "contains", new Object());
+      ensureTREBehaviour(false, managedEm, "createNamedQuery", "hi");
+      ensureTREBehaviour(false, managedEm, "createNativeQuery", "hi");
+      ensureTREBehaviour(false, managedEm, "createNativeQuery", "hi", Object.class);
+      ensureTREBehaviour(false, managedEm, "createNativeQuery", "hi", "hi");
+      ensureTREBehaviour(false, managedEm, "createQuery", "hi");
+      ensureTREBehaviour(false, managedEm, "find", Object.class, new Object());
+      ensureTREBehaviour(false, managedEm, "flush");
+      ensureTREBehaviour(false, managedEm, "getDelegate");
+      ensureTREBehaviour(false, managedEm, "getFlushMode");
+      ensureTREBehaviour(false, managedEm, "getReference", Object.class, new Object());
+      ensureTREBehaviour(false, managedEm, "lock", new Object(), LockModeType.NONE);
+      ensureTREBehaviour(false, managedEm, "merge", new Object());
+      ensureTREBehaviour(false, managedEm, "persist", new Object());
+      ensureTREBehaviour(false, managedEm, "refresh", new Object());
+      ensureTREBehaviour(false, managedEm, "remove", new Object());
+      ensureTREBehaviour(false, managedEm, "setFlushMode", FlushModeType.AUTO);
+      ensureTREBehaviour(false, managedEm, "createNamedQuery", "hi", Object.class);
+      ensureTREBehaviour(false, managedEm, "createQuery", Proxy.newProxyInstance(this.getClass().getClassLoader(),
+         new Class[] {CriteriaQuery.class}, new InvocationHandler() {
+          
+          public Object invoke(Object proxy, Method method, Object[] args)
+              throws Throwable {
+            return null;
+          }
+        }));
+      ensureTREBehaviour(false, managedEm, "createQuery", "hi", Object.class);
+      ensureTREBehaviour(false, managedEm, "detach", new Object());
+      ensureTREBehaviour(false, managedEm, "find", Object.class, new Object(), new HashMap());
+      ensureTREBehaviour(false, managedEm, "find", Object.class, new Object(), LockModeType.NONE);
+      ensureTREBehaviour(false, managedEm, "find", Object.class, new Object(), LockModeType.OPTIMISTIC);
+      ensureTREBehaviour(false, managedEm, "find", Object.class, new Object(), LockModeType.NONE, 
+          new HashMap());
+      ensureTREBehaviour(false, managedEm, "find", Object.class, new Object(), LockModeType.OPTIMISTIC, 
+          new HashMap());
+      ensureTREBehaviour(false, managedEm, "getCriteriaBuilder");
+      ensureTREBehaviour(false, managedEm, "getLockMode", new Object());
+      ensureTREBehaviour(false, managedEm, "getMetamodel");
+      ensureTREBehaviour(false, managedEm, "getProperties");
+      ensureTREBehaviour(false, managedEm, "lock", new Object(), LockModeType.NONE, new HashMap());
+      ensureTREBehaviour(false, managedEm, "refresh", new Object(), new HashMap());
+      ensureTREBehaviour(false, managedEm, "refresh", new Object(), LockModeType.NONE);
+      ensureTREBehaviour(false, managedEm, "refresh", new Object(), LockModeType.NONE, new HashMap());
+      ensureTREBehaviour(false, managedEm, "setProperty", "hi", new Object());
+      ensureTREBehaviour(false, managedEm, "unwrap", Object.class);
+    } finally {
+      ut.rollback();
+    }
+  }
+  
+  @Test
+  public void testNonTxEmIsCleared() throws Exception {
+    
+    registerClient("bp-test-unit");
+    
+    EntityManagerFactory emf = getProxyEMF("bp-test-unit");
+    
+    final EntityManager managedEm = emf.createEntityManager();
+    
+    UserTransaction ut = getOsgiService(UserTransaction.class);
+    
+    ut.begin();
+    try {
+      
+      Query q = managedEm.createQuery("DELETE from Car c");
+      q.executeUpdate();
+      
+      q = managedEm.createQuery("SELECT Count(c) from Car c");
+      assertEquals(0l, q.getSingleResult());
+      
+      Car car = new Car();
+      car.setNumberOfSeats(5);
+      car.setEngineSize(1200);
+      car.setColour("blue");
+      car.setNumberPlate("A1AAA");
+      managedEm.persist(car);
+    } catch (Exception e) {
+      e.printStackTrace();
+    }finally {
+      ut.commit();
+    }
+    
+    Car c = managedEm.find(Car.class, "A1AAA");
+    
+    assertEquals(5, c.getNumberOfSeats());
+    assertEquals(1200, c.getEngineSize());
+    assertEquals("blue", c.getColour());
+    
+    ut.begin();
+    try {
+      Car car = managedEm.find(Car.class, "A1AAA");
+      car.setNumberOfSeats(2);
+      car.setEngineSize(2000);
+      car.setColour("red");
+    } finally {
+      ut.commit();
+    }
+    
+    c = managedEm.find(Car.class, "A1AAA");
+    
+    assertEquals(2, c.getNumberOfSeats());
+    assertEquals(2000, c.getEngineSize());
+    assertEquals("red", c.getColour());
+    
+  }
+
+  @Test
+  public void testNonTxQueries() throws Exception {
     
+    registerClient("bp-test-unit");
+    
+    EntityManagerFactory emf = getProxyEMF("bp-test-unit");
+    
+    final EntityManager managedEm = emf.createEntityManager();
+    
+    UserTransaction ut = getOsgiService(UserTransaction.class);
+    
+    ut.begin();
+    try {
+      
+      Query q = managedEm.createQuery("DELETE from Car c");
+      q.executeUpdate();
+      
+      q = managedEm.createQuery("SELECT Count(c) from Car c");
+      assertEquals(0l, q.getSingleResult());
+    } finally {
+      ut.commit();
+    }
+    
+    Query countQuery = managedEm.createQuery("SELECT Count(c) from Car c");
+    assertEquals(0l, countQuery.getSingleResult());
+    
+    ut.begin();
+    try {
+      Car car = new Car();
+      car.setNumberOfSeats(5);
+      car.setEngineSize(1200);
+      car.setColour("blue");
+      car.setNumberPlate("A1AAA");
+      managedEm.persist(car);
+      
+      car = new Car();
+      car.setNumberOfSeats(7);
+      car.setEngineSize(1800);
+      car.setColour("green");
+      car.setNumberPlate("B2BBB");
+      managedEm.persist(car);
+    } finally {
+      ut.commit();
+    }
+    
+    assertEquals(2l, countQuery.getSingleResult());
+    
+    TypedQuery<Car> carQuery = managedEm.
+             createQuery("Select c from Car c ORDER by c.engineSize", Car.class);
+    
+    List<Car> list = carQuery.getResultList();
+    assertEquals(2l, list.size());
+    
+    assertEquals(5, list.get(0).getNumberOfSeats());
+    assertEquals(1200, list.get(0).getEngineSize());
+    assertEquals("blue", list.get(0).getColour());
+    assertEquals("A1AAA", list.get(0).getNumberPlate());
+    
+    assertEquals(7, list.get(1).getNumberOfSeats());
+    assertEquals(1800, list.get(1).getEngineSize());
+    assertEquals("green", list.get(1).getColour());
+    assertEquals("B2BBB", list.get(1).getNumberPlate());
+    
+    ut.begin();
+    try {
+      Car car = managedEm.find(Car.class, "A1AAA");
+      car.setNumberOfSeats(2);
+      car.setEngineSize(2000);
+      car.setColour("red");
+      
+      car = managedEm.find(Car.class, "B2BBB");
+      managedEm.remove(car);
+      
+      car = new Car();
+      car.setNumberOfSeats(2);
+      car.setEngineSize(800);
+      car.setColour("black");
+      car.setNumberPlate("C3CCC");
+      managedEm.persist(car);
+      
+    } finally {
+      ut.commit();
+    }
+    
+    assertEquals(2l, countQuery.getSingleResult());
+    
+    list = carQuery.getResultList();
+    assertEquals(2l, list.size());
+    
+    assertEquals(2, list.get(0).getNumberOfSeats());
+    assertEquals(800, list.get(0).getEngineSize());
+    assertEquals("black", list.get(0).getColour());
+    assertEquals("C3CCC", list.get(0).getNumberPlate());
+    
+    assertEquals(5, list.get(1).getNumberOfSeats());
+    assertEquals(1200, list.get(1).getEngineSize());
+    assertEquals("blue", list.get(1).getColour());
+    assertEquals("A1AAA", list.get(1).getNumberPlate());
+  }
+  
+  private void registerClient(String name) {
+    PersistenceContextProvider provider = getOsgiService(PersistenceContextProvider.class);
+    
+    HashMap<String, Object> props = new HashMap<String, Object>();
+    props.put(PersistenceContextProvider.PERSISTENCE_CONTEXT_TYPE, PersistenceContextType.TRANSACTION);
+    provider.registerContext(name, bundleContext.getBundle(), props);
   }
 
+  private void ensureTREBehaviour(boolean expectedToFail, EntityManager em, String methodName, Object... args) throws Exception {
+    
+    List<Class> argTypes = new ArrayList<Class>();
+    for(Object o : args) {
+      if(o instanceof Map)
+        argTypes.add(Map.class);
+      else if (o instanceof CriteriaQuery)
+        argTypes.add(CriteriaQuery.class);
+      else
+        argTypes.add(o.getClass());
+    }
+    
+    Method m = EntityManager.class.getMethod(methodName, 
+        argTypes.toArray(new Class[args.length]));
+    
+    try {
+      m.invoke(em, args);
+      if(expectedToFail)
+        fail("A transaction is required");
+    } catch (InvocationTargetException ite) {
+      if(expectedToFail && 
+          !!!(ite.getCause() instanceof TransactionRequiredException))
+        fail("We got the wrong failure. Expected a TransactionRequiredException" +
+        		", got a " + ite.toString());
+      else if (!!!expectedToFail && 
+          ite.getCause() instanceof TransactionRequiredException)
+        fail("We got the wrong failure. Expected not to get a TransactionRequiredException" +
+            ", but we got one anyway!");
+    }
+  }
+  
   @org.ops4j.pax.exam.junit.Configuration
   public static Option[] configuration() {
     Option[] options = options(
-        bootDelegation(),
-        
+        bootDelegationPackages("javax.transaction", "javax.transaction.*"),
+        vmOption("-Dorg.osgi.framework.system.packages=javax.accessibility,javax.activation,javax.activity,javax.annotation,javax.annotation.processing,javax.crypto,javax.crypto.interfaces,javax.crypto.spec,javax.imageio,javax.imageio.event,javax.imageio.metadata,javax.imageio.plugins.bmp,javax.imageio.plugins.jpeg,javax.imageio.spi,javax.imageio.stream,javax.jws,javax.jws.soap,javax.lang.model,javax.lang.model.element,javax.lang.model.type,javax.lang.model.util,javax.management,javax.management.loading,javax.management.modelmbean,javax.management.monitor,javax.management.openmbean,javax.management.relation,javax.management.remote,javax.management.remote.rmi,javax.management.timer,javax.naming,javax.naming.directory,javax.naming.event,javax.naming.ldap,javax.naming.spi,javax.net,javax.net.ssl,javax.print,javax.print.attribute,javax.print.attribute.standard,javax.print.event,javax.rmi,javax.rmi.CORBA,javax.rmi.ssl,javax.script,javax.security.auth,javax.security.auth.callback,
 javax.security.auth.kerberos,javax.security.auth.login,javax.security.auth.spi,javax.security.auth.x500,javax.security.cert,javax.security.sasl,javax.sound.midi,javax.sound.midi.spi,javax.sound.sampled,javax.sound.sampled.spi,javax.sql,javax.sql.rowset,javax.sql.rowset.serial,javax.sql.rowset.spi,javax.swing,javax.swing.border,javax.swing.colorchooser,javax.swing.event,javax.swing.filechooser,javax.swing.plaf,javax.swing.plaf.basic,javax.swing.plaf.metal,javax.swing.plaf.multi,javax.swing.plaf.synth,javax.swing.table,javax.swing.text,javax.swing.text.html,javax.swing.text.html.parser,javax.swing.text.rtf,javax.swing.tree,javax.swing.undo,javax.tools,javax.xml,javax.xml.bind,javax.xml.bind.annotation,javax.xml.bind.annotation.adapters,javax.xml.bind.attachment,javax.xml.bind.helpers,javax.xml.bind.util,javax.xml.crypto,javax.xml.crypto.dom,javax.xml.crypto.dsig,javax.xml.crypto.dsig.dom,javax.xml.crypto.dsig.keyinfo,javax.xml.crypto.dsig.spec,javax.xml.datatype,javax.xml.name
 space,javax.xml.parsers,javax.xml.soap,javax.xml.stream,javax.xml.stream.events,javax.xml.stream.util,javax.xml.transform,javax.xml.transform.dom,javax.xml.transform.sax,javax.xml.transform.stax,javax.xml.transform.stream,javax.xml.validation,javax.xml.ws,javax.xml.ws.handler,javax.xml.ws.handler.soap,javax.xml.ws.http,javax.xml.ws.soap,javax.xml.ws.spi,javax.xml.xpath,org.ietf.jgss,org.omg.CORBA,org.omg.CORBA.DynAnyPackage,org.omg.CORBA.ORBPackage,org.omg.CORBA.TypeCodePackage,org.omg.CORBA.portable,org.omg.CORBA_2_3,org.omg.CORBA_2_3.portable,org.omg.CosNaming,org.omg.CosNaming.NamingContextExtPackage,org.omg.CosNaming.NamingContextPackage,org.omg.Dynamic,org.omg.DynamicAny,org.omg.DynamicAny.DynAnyFactoryPackage,org.omg.DynamicAny.DynAnyPackage,org.omg.IOP,org.omg.IOP.CodecFactoryPackage,org.omg.IOP.CodecPackage,org.omg.Messaging,org.omg.PortableInterceptor,org.omg.PortableInterceptor.ORBInitInfoPackage,org.omg.PortableServer,org.omg.PortableServer.CurrentPackage,org.omg.
 PortableServer.POAManagerPackage,org.omg.PortableServer.POAPackage,org.omg.PortableServer.ServantLocatorPackage,org.omg.PortableServer.portable,org.omg.SendingContext,org.omg.stub.java.rmi,org.w3c.dom,org.w3c.dom.bootstrap,org.w3c.dom.css,org.w3c.dom.events,org.w3c.dom.html,org.w3c.dom.ls,org.w3c.dom.ranges,org.w3c.dom.stylesheets,org.w3c.dom.traversal,org.w3c.dom.views,org.xml.sax,org.xml.sax.ext,org.xml.sax.helpers,javax.transaction;partial=true;mandatory:=partial,javax.transaction.xa;partial=true;mandatory:=partial"),
         // Log
         mavenBundle("org.ops4j.pax.logging", "pax-logging-api"),
         mavenBundle("org.ops4j.pax.logging", "pax-logging-service"),
@@ -107,9 +431,14 @@ public class JPAContextTest {
         // Adding blueprint to the runtime is a hack to placate the maven bundle plugin. 
         mavenBundle("org.apache.aries.blueprint", "org.apache.aries.blueprint"),
         mavenBundle("org.apache.geronimo.specs", "geronimo-jpa_2.0_spec"),
+        mavenBundle("org.apache.aries.jndi", "org.apache.aries.jndi.api"),
+        mavenBundle("org.apache.aries.jndi", "org.apache.aries.jndi.core"),
+        mavenBundle("org.apache.aries.jndi", "org.apache.aries.jndi.url"),
         mavenBundle("org.apache.aries.jpa", "org.apache.aries.jpa.api"),
         mavenBundle("org.apache.aries.jpa", "org.apache.aries.jpa.container"),
         mavenBundle("org.apache.aries.jpa", "org.apache.aries.jpa.container.context"),
+        mavenBundle("org.apache.aries.transaction", "org.apache.aries.transaction.manager" ),
+        mavenBundle("org.apache.aries.transaction", "org.apache.aries.transaction.wrappers" ),
         mavenBundle("org.apache.derby", "derby"),
         mavenBundle("org.apache.geronimo.specs", "geronimo-jta_1.1_spec"),
         mavenBundle("commons-lang", "commons-lang"),
@@ -124,6 +453,9 @@ public class JPAContextTest {
         
         mavenBundle("org.apache.aries.jpa", "org.apache.aries.jpa.container.itest.bundle"),
         
+//        vmOption ("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5006"),
+//        waitForFrameworkStartup(),
+        
         equinox().version("3.5.0"));
     options = updateOptions(options);
     return options;

Modified: incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml?rev=1049643&r1=1049642&r2=1049643&view=diff
==============================================================================
--- incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml (original)
+++ incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml Wed Dec 15 16:57:29 2010
@@ -33,11 +33,17 @@
     </properties>
   </persistence-unit>
   
-  <persistence-unit name="bp-test-unit" transaction-type="RESOURCE_LOCAL">
+  <persistence-unit name="bp-test-unit" transaction-type="JTA">
     <description>Test persistence unit for the JPA Container and Context iTests</description>
     <jta-data-source>blueprint:comp/jta</jta-data-source>
     <non-jta-data-source>blueprint:comp/nonjta</non-jta-data-source>
     <class>org.apache.aries.jpa.container.itest.entities.Car</class>
     <exclude-unlisted-classes>true</exclude-unlisted-classes>
+    <properties>
+     <!-- These properties are creating the database on the fly. We are using them to avoid the tests having
+          to create a database  -->
+     <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+     <property name="openjpa.jdbc.DBDictionary" value="derby"/>
+    </properties>
   </persistence-unit>
 </persistence>

Modified: incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml?rev=1049643&r1=1049642&r2=1049643&view=diff
==============================================================================
--- incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml (original)
+++ incubator/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml Wed Dec 15 16:57:29 2010
@@ -16,11 +16,6 @@
     limitations under the License.
 -->
 <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
-
-  <bean id="jta" class="org.apache.derby.jdbc.EmbeddedDataSource">
-    <property name="databaseName" value="memory:testDB"/>
-    <property name="createDatabase" value="create"/> 
-  </bean>
   
   <bean id="nonjta" class="org.apache.derby.jdbc.EmbeddedDataSource">
     <property name="databaseName" value="memory:testDB"/> 
@@ -28,7 +23,17 @@
   </bean>
   
   
-  <service ref="jta" interface="javax.sql.DataSource"/>
+  <service interface="javax.sql.XADataSource">
+    <service-properties>
+      <entry key="transactional" value="true"/>
+    </service-properties>
+    <bean class="org.apache.derby.jdbc.EmbeddedXADataSource">
+    	<property name="databaseName" value="memory:testDB"/>
+    	<property name="createDatabase" value="create"/> 
+  	</bean>
+  </service>
     
+  <reference id="jta" availability="optional" interface="javax.sql.DataSource"
+             filter="(transactional=true)"/>
 </blueprint>
 

Modified: incubator/aries/trunk/jpa/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jpa/pom.xml?rev=1049643&r1=1049642&r2=1049643&view=diff
==============================================================================
--- incubator/aries/trunk/jpa/pom.xml (original)
+++ incubator/aries/trunk/jpa/pom.xml Wed Dec 15 16:57:29 2010
@@ -180,6 +180,12 @@
               <version>0.3-incubating-SNAPSHOT</version>
             </dependency>
             <dependency>
+              <groupId>org.apache.aries.transaction</groupId>
+              <artifactId>org.apache.aries.transaction.wrappers</artifactId>
+              <scope>test</scope>
+              <version>0.3-incubating-SNAPSHOT</version>
+            </dependency>
+            <dependency>
               <groupId>org.apache.aries.jndi</groupId>
               <artifactId>org.apache.aries.jndi.api</artifactId>
               <scope>test</scope>