cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From aadamc...@apache.org
Subject svn commit: r503390 - in /cayenne/main/trunk/framework/cayenne-jpa-unpublished: ./ src/main/java/org/apache/cayenne/jpa/ src/main/java/org/apache/cayenne/jpa/conf/ src/test/java/org/apache/cayenne/jpa/
Date Sun, 04 Feb 2007 11:31:15 GMT
Author: aadamchik
Date: Sun Feb  4 03:31:14 2007
New Revision: 503390

URL: http://svn.apache.org/viewvc?view=rev&rev=503390
Log:
CAY-744: JTA EntityManager
(mostly done, need to do some integration testing)

Added:
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManager.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManagerFactory.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactory.java
      - copied, changed from r503214, cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JpaEntityManagerFactory.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/MockObjectContext.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactoryTest.java
      - copied, changed from r503207, cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerFactoryTest.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerTest.java
      - copied, changed from r503207, cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerTest.java
Removed:
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JpaEntityManager.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JpaEntityManagerFactory.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerFactoryTest.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerTest.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/MockJpaEntityManager.java
Modified:
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/pom.xml
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManager.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/DefaultDataSourceFactory.java
    cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/JpaUnit.java

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/pom.xml
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/pom.xml?view=diff&rev=503390&r1=503389&r2=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/pom.xml (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/pom.xml Sun Feb  4 03:31:14 2007
@@ -45,6 +45,11 @@
 			<groupId>org.apache.geronimo.specs</groupId>
 			<artifactId>geronimo-jpa_3.0_spec</artifactId>
 		</dependency>
+		
+		<dependency>
+				<groupId>org.apache.geronimo.specs</groupId>
+				<artifactId>geronimo-jta_1.1_spec</artifactId>
+		</dependency>
 
 		<dependency>
 			<groupId>org.apache.cayenne.unpublished</groupId>

Added: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManager.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManager.java?view=auto&rev=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManager.java (added)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManager.java Sun Feb  4 03:31:14 2007
@@ -0,0 +1,138 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.jpa;
+
+import javax.persistence.EntityTransaction;
+import javax.persistence.TransactionRequiredException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.TransactionSynchronizationRegistry;
+
+import org.apache.cayenne.ObjectContext;
+
+/**
+ * An EntityManager that can participate in JTA transactions.
+ * 
+ * @author Andrus Adamchik
+ */
+public class JtaEntityManager extends ResourceLocalEntityManager {
+
+    protected Object currentTxKey;
+
+    public JtaEntityManager(ObjectContext context, JtaEntityManagerFactory factory) {
+        super(context, factory);
+    }
+
+    private JtaEntityManagerFactory getJtaFactory() {
+        return (JtaEntityManagerFactory) getFactory();
+    }
+
+    /**
+     * @throws IllegalStateException, as this entity manager is of JTA kind.
+     */
+    public EntityTransaction getTransaction() {
+        throw new IllegalStateException(
+                "'getTransaction' is called on a JTA EntityManager");
+    }
+
+    /**
+     * Indicates to the EntityManager that a JTA transaction is active. This method should
+     * be called on a JTA application managed EntityManager that was created outside the
+     * scope of the active transaction to associate it with the current JTA transaction.
+     * 
+     * @throws TransactionRequiredException if there is no transaction.
+     */
+    @Override
+    public void joinTransaction() {
+        if (currentTxKey == null) {
+            TransactionSynchronizationRegistry registry = getJtaFactory()
+                    .getTransactionRegistry();
+            registry.registerInterposedSynchronization(new TransactionBinding());
+            currentTxKey = registry.getTransactionKey();
+        }
+    }
+
+    /**
+     * @throws TransactionRequiredException if there is no transaction.
+     */
+    @Override
+    public void persist(Object entity) {
+        checkTransaction();
+        super.persist(entity);
+    }
+
+    /**
+     * @throws TransactionRequiredException if there is no transaction.
+     */
+    @Override
+    public <T> T merge(T entity) {
+        checkTransaction();
+        return super.merge(entity);
+    }
+
+    /**
+     * @throws TransactionRequiredException if there is no transaction.
+     */
+    @Override
+    public void remove(Object entity) {
+        checkTransaction();
+        super.remove(entity);
+    }
+
+    /**
+     * @throws TransactionRequiredException if there is no transaction.
+     */
+    @Override
+    public void refresh(Object entity) {
+        checkTransaction();
+        super.refresh(entity);
+    }
+
+    /**
+     * @throws TransactionRequiredException if there is no transaction.
+     */
+    public void flush() {
+        checkTransaction();
+        super.flush();
+    };
+
+    /**
+     * @throws TransactionRequiredException if there is no transaction in progress.
+     */
+    protected void checkTransaction() throws TransactionRequiredException {
+        if (!getJtaFactory().isActiveTransaction()) {
+            throw new TransactionRequiredException();
+        }
+    }
+
+    class TransactionBinding implements Synchronization {
+
+        public void afterCompletion(int status) {
+            if (status != Status.STATUS_COMMITTED) {
+                clear();
+            }
+
+            currentTxKey = null;
+        }
+
+        public void beforeCompletion() {
+            flush();
+        }
+    }
+}

Added: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManagerFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManagerFactory.java?view=auto&rev=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManagerFactory.java (added)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JtaEntityManagerFactory.java Sun Feb  4 03:31:14 2007
@@ -0,0 +1,103 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.jpa;
+
+import java.util.Map;
+
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import javax.persistence.EntityManager;
+import javax.persistence.spi.PersistenceUnitInfo;
+import javax.transaction.Status;
+import javax.transaction.TransactionSynchronizationRegistry;
+
+import org.apache.cayenne.access.DataDomain;
+
+/**
+ * An EntityManagerFactory that registers all EntityManagers that it creates with an
+ * active JTA Transaction so that they could flush the object state to the database during
+ * commit.
+ * 
+ * @author Andrus Adamchik
+ */
+public class JtaEntityManagerFactory extends ResourceLocalEntityManagerFactory {
+
+    static final String TX_SYNC_REGISTRY_KEY = "java:comp/TransactionSynchronizationRegistry";
+
+    protected TransactionSynchronizationRegistry transactionRegistry;
+
+    /**
+     * Non-public constructor used for unit testing.
+     */
+    JtaEntityManagerFactory(PersistenceUnitInfo unitInfo) {
+        super(unitInfo);
+    }
+
+    public JtaEntityManagerFactory(Provider provider, DataDomain domain,
+            PersistenceUnitInfo unitInfo) {
+        super(provider, domain, unitInfo);
+    }
+
+    /**
+     * Returns JTA 11 TransactionSynchronizationRegistry, looking it up via JNDI on first
+     * access, and caching it for the following invocations.
+     */
+    protected TransactionSynchronizationRegistry getTransactionRegistry() {
+        if (transactionRegistry == null) {
+            InitialContext jndiContext;
+            try {
+                jndiContext = new InitialContext();
+            }
+            catch (NamingException e) {
+                throw new JpaProviderException("Error creating JNDI context", e);
+            }
+
+            try {
+                transactionRegistry = (TransactionSynchronizationRegistry) jndiContext
+                        .lookup(TX_SYNC_REGISTRY_KEY);
+            }
+            catch (NamingException e) {
+                throw new JpaProviderException("Failed to look up "
+                        + TX_SYNC_REGISTRY_KEY, e);
+            }
+        }
+
+        return transactionRegistry;
+    }
+
+    /**
+     * Returns whether there is a JTA transaction in progress.
+     */
+    protected boolean isActiveTransaction() {
+        int txStatus = getTransactionRegistry().getTransactionStatus();
+        return txStatus == Status.STATUS_ACTIVE
+                || txStatus == Status.STATUS_MARKED_ROLLBACK;
+    }
+
+    @Override
+    protected EntityManager createEntityManagerInternal(Map map) {
+        EntityManager em = new JtaEntityManager(domain.createDataContext(), this);
+
+        if (isActiveTransaction()) {
+            em.joinTransaction();
+        }
+
+        return em;
+    }
+}

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java?view=diff&rev=503390&r1=503389&r2=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/Provider.java Sun Feb  4 03:31:14 2007
@@ -73,19 +73,19 @@
  */
 public class Provider implements PersistenceProvider {
 
-    // common properties
+    // spec-defined properties per ch. 7.1.3.1.
     public static final String PROVIDER_PROPERTY = "javax.persistence.provider";
     public static final String TRANSACTION_TYPE_PROPERTY = "javax.persistence.transactionType";
     public static final String JTA_DATA_SOURCE_PROPERTY = "javax.persistence.jtaDataSource";
     public static final String NON_JTA_DATA_SOURCE_PROPERTY = "javax.persistence.nonJtaDataSource";
 
-    // provider-specific properties
+    // provider-specific properties. Must use provider namespace per ch. 7.1.3.1.
     public static final String DATA_SOURCE_FACTORY_PROPERTY = "org.apache.cayenne.jpa.jpaDataSourceFactory";
     public static final String UNIT_FACTORY_PROPERTY = "org.apache.cayenne.jpa.jpaUnitFactory";
+    public static final String CREATE_SCHEMA_PROPERTY = "cayenne.schema.create";
 
     public static final String INSTRUMENTING_FACTORY_CLASS = InstrumentingUnitFactory.class
             .getName();
-    public static final String CREATE_SCHEMA_PROPERTY = "cayenne.schema.create";
 
     protected boolean validateDescriptors;
     protected UnitLoader unitLoader;
@@ -153,6 +153,11 @@
         }
     }
 
+    /**
+     * Called by Persistence class when an EntityManagerFactory is to be created. Creates
+     * a {@link JpaUnit} and calls
+     * {@link #createContainerEntityManagerFactory(PersistenceUnitInfo, Map)}.
+     */
     public EntityManagerFactory createEntityManagerFactory(String emName, Map map) {
 
         // TODO: Andrus, 2/11/2006 - cache loaded units (or factories)...
@@ -182,25 +187,33 @@
             return null;
         }
 
-        return createContainerEntityManagerFactory(ui, map);
+        // do not pass properties further down, they are already acounted for in the
+        // PersistenceUnitInfo.
+        return createContainerEntityManagerFactory(ui, null);
     }
 
     /**
-     * Maps PersistenceUnitInfo to Cayenne DataDomain and returns a
-     * {@link EntityManagerFactory} which is a DataDomain wrapper.
+     * Called by the container when an EntityManagerFactory is to be created. Returns a
+     * {@link EntityManagerFactory} which is a DataDomain wrapper. Note that Cayenne
+     * provider will ignore all but 'javax.persistence.transactionType' property in the
+     * passed property map.
      */
-    // TODO: andrus, 07/24/2006 - extract properties from the second map parameter as well
-    // as PUI.
     public synchronized EntityManagerFactory createContainerEntityManagerFactory(
-            PersistenceUnitInfo info,
+            PersistenceUnitInfo unit,
             Map map) {
-        String name = info.getPersistenceUnitName();
+
+        String name = unit.getPersistenceUnitName();
         DataDomain domain = configuration.getDomain(name);
 
+        // TODO: andrus, 2/3/2007 - considering property overrides, it may be a bad idea
+        // to cache domains. Essentially we are caching a PersistenceUnitInfo with a given
+        // name, without a possibility to refresh it. But maybe this is ok...?
         if (domain == null) {
 
             long t0 = System.currentTimeMillis();
 
+            boolean isJTA = isJta(unit, map);
+
             // configure Cayenne domain
             domain = new DataDomain(name);
             ClassDescriptorMap descriptors = domain
@@ -210,7 +223,7 @@
             descriptors.addFactory(new JpaClassDescriptorFactory(descriptors));
             configuration.addDomain(domain);
 
-            EntityMapLoader loader = new EntityMapLoader(info);
+            EntityMapLoader loader = new EntityMapLoader(unit);
 
             // we must set enhancer in this exact place, between JPA and Cayenne mapping
             // loading. By now all the JpaEntities are loaded (using separate unit class
@@ -219,32 +232,31 @@
                     .getEntityMap()
                     .getMangedClasses();
 
-            info.addTransformer(new UnitClassTranformer(managedClasses, new Enhancer(
+            unit.addTransformer(new UnitClassTranformer(managedClasses, new Enhancer(
                     new JpaEnhancerVisitorFactory(managedClasses))));
 
             DataMapConverter converter = new DataMapConverter();
             DataMap cayenneMap = converter.toDataMap(name, loader.getContext());
 
-            DataSource dataSource = info.getTransactionType() == PersistenceUnitTransactionType.JTA
-                    ? info.getJtaDataSource()
-                    : info.getNonJtaDataSource();
-
-            DbAdapter adapter = createCustomAdapter(loader.getContext(), info);
+            // TODO: andrus, 2/3/2007 - clarify this logic.... JTA EM may not always mean
+            // JTA DS?
+            DataSource dataSource = isJTA ? unit.getJtaDataSource() : unit
+                    .getNonJtaDataSource();
 
+            DbAdapter adapter = createCustomAdapter(loader.getContext(), unit);
             DataNode node = new DataNode(name);
-
             if (adapter == null) {
                 adapter = new AutoAdapter(new NodeDataSource(node));
             }
 
             node.setAdapter(adapter);
-
             node.setDataSource(dataSource);
             node.addDataMap(cayenneMap);
 
             domain.addNode(node);
+            domain.setUsingExternalTransactions(isJTA);
 
-            if ("true".equalsIgnoreCase(info.getProperties().getProperty(
+            if ("true".equalsIgnoreCase(unit.getProperties().getProperty(
                     CREATE_SCHEMA_PROPERTY))) {
                 loadSchema(dataSource, adapter, cayenneMap);
             }
@@ -268,9 +280,30 @@
             }
         }
 
-        JpaEntityManagerFactory factory = new JpaEntityManagerFactory(domain, info);
-        factory.setDelegate(this);
-        return factory;
+        // see TODO above - JTA vs RESOURCE_LOCAL is cached per domain... maybe need to
+        // change that
+        return domain.isUsingExternalTransactions() ? new JtaEntityManagerFactory(
+                this,
+                domain,
+                unit) : new ResourceLocalEntityManagerFactory(this, domain, unit);
+    }
+
+    /**
+     * Returns whether provided configuration specifies a JTA or RESOURCE_LOCAL
+     * EntityManager.
+     */
+    private boolean isJta(PersistenceUnitInfo unit, Map overrides) {
+        PersistenceUnitTransactionType txType;
+        String txTypeOverride = (overrides != null) ? (String) overrides
+                .get(TRANSACTION_TYPE_PROPERTY) : null;
+        if (txTypeOverride != null) {
+            txType = PersistenceUnitTransactionType.valueOf(txTypeOverride);
+        }
+        else {
+            txType = unit.getTransactionType();
+        }
+
+        return txType == PersistenceUnitTransactionType.JTA;
     }
 
     /**

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManager.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManager.java?view=diff&rev=503390&r1=503389&r2=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManager.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManager.java Sun Feb  4 03:31:14 2007
@@ -19,9 +19,10 @@
 
 package org.apache.cayenne.jpa;
 
-import java.util.Map;
-
+import javax.persistence.EntityManager;
+import javax.persistence.EntityNotFoundException;
 import javax.persistence.EntityTransaction;
+import javax.persistence.FlushModeType;
 import javax.persistence.LockModeType;
 import javax.persistence.PersistenceException;
 import javax.persistence.Query;
@@ -33,51 +34,157 @@
 import org.apache.cayenne.Persistent;
 import org.apache.cayenne.access.Transaction;
 
-public class ResourceLocalEntityManager extends JpaEntityManager {
+public class ResourceLocalEntityManager implements EntityManager {
+
+    protected EntityTransaction transaction;
+    protected ResourceLocalEntityManagerFactory factory;
+    protected FlushModeType flushMode;
+    protected boolean open;
+    protected ObjectContext context;
 
-    private ObjectContext context;
+    public ResourceLocalEntityManager(ObjectContext context,
+            ResourceLocalEntityManagerFactory factory) {
+
+        if (factory == null) {
+            throw new IllegalArgumentException("Null entity manager factory");
+        }
 
-    public ResourceLocalEntityManager(ObjectContext context, JpaEntityManagerFactory factory,
-            Map parameters) {
-        super(factory);
+        this.open = true;
         this.context = context;
+        this.factory = factory;
     }
 
-    @Override
-    protected EntityTransaction createResourceLocalTransaction() {
-        return new JpaTransaction(Transaction.internalTransaction(null), this);
+    /**
+     * Returns parent EntityManagerFactory.
+     */
+    protected ResourceLocalEntityManagerFactory getFactory() {
+        return factory;
     }
 
-    @Override
-    protected void persistInternal(Object entity) {
+    /**
+     * Close an application-managed EntityManager. After an EntityManager has been closed,
+     * all methods on the EntityManager instance will throw the IllegalStateException
+     * except for isOpen, which will return false. This method can only be called when the
+     * EntityManager is not associated with an active transaction.
+     * 
+     * @throws IllegalStateException if the EntityManager is associated with an active
+     *             transaction or if the EntityManager is container-managed.
+     */
+    public void close() {
+        checkClosed();
+
+        if (transaction != null && transaction.isActive()) {
+            throw new IllegalStateException("Active transaction in progress");
+        }
+
+        open = false;
+    }
+
+    public boolean isOpen() {
+        return open && (factory == null || factory.isOpen());
+    }
+
+    public Object getDelegate() {
+        return factory.getProvider();
+    }
+
+    /**
+     * Make an instance managed and persistent.
+     * 
+     * @param entity an object to be made persistent
+     * @throws IllegalArgumentException if not an entity.
+     */
+    public void persist(Object entity) {
+        checkClosed();
         checkEntityType(entity);
         context.registerNewObject(entity);
     }
 
-    @Override
-    protected <T> T mergeInternal(T entity) {
+    /**
+     * Merge the state of the given entity into the current persistence context. Cayenne:
+     * Is this like localObject(s)?
+     * 
+     * @param entity
+     * @return the instance that the state was merged to
+     * @throws IllegalArgumentException if instance is not an entity or is a removed
+     *             entity
+     */
+    public <T> T merge(T entity) {
+        checkClosed();
         checkEntityType(entity);
         checkNotRemoved(entity);
         Persistent persistent = (Persistent) entity;
         return (T) context.localObject(persistent.getObjectId(), persistent);
     }
 
-    @Override
-    protected void removeInternal(Object entity) {
+    /**
+     * Remove the entity instance.
+     * 
+     * @param entity
+     * @throws IllegalArgumentException if not an entity or if a detached entity.
+     */
+    public void remove(Object entity) {
+        checkClosed();
         checkEntityType(entity);
         checkAttached(entity);
         context.deleteObject((Persistent) entity);
     }
 
-    @Override
-    protected <T> T findInternal(Class<T> entityClass, Object primaryKey) {
+    /**
+     * Find by primary key.
+     * 
+     * @param entityClass
+     * @param primaryKey
+     * @return the found entity instance or null if the entity does not exist
+     * @throws IllegalArgumentException if the first argument does not denote an entity
+     *             type or the second argument is not a valid type for that
+     */
+    public <T> T find(Class<T> entityClass, Object primaryKey) {
+        checkClosed();
         checkEntityType(entityClass);
-        checkIdType(entityClass, primaryKey);
         return (T) DataObjectUtils.objectForPK(context, entityClass, primaryKey);
     }
 
-    @Override
-    protected void flushInternal() {
+    /**
+     * Get an instance, whose state may be lazily fetched. If the requested instance does
+     * not exist in the database, throws EntityNotFoundException when the instance state
+     * is first accessed. (The persistence provider runtime is permitted to throw the
+     * EntityNotFoundException when getReference is called.) The application should not
+     * expect that theinstance state will be available upon detachment, unless it was
+     * accessed by the application while the entity manager was open.
+     * 
+     * @param entityClass
+     * @param primaryKey
+     * @return the found entity instance
+     * @throws IllegalArgumentException if the first argument does not denote an entity
+     *             type or the second argument is not a valid type for that entityƕs
+     *             primary key
+     * @throws EntityNotFoundException if the entity state cannot be accessed
+     */
+    public <T> T getReference(Class<T> entityClass, Object primaryKey) {
+        checkClosed();
+
+        // TODO: force refresh?
+        T ref = find(entityClass, primaryKey);
+
+        if (ref == null) {
+            throw new EntityNotFoundException("Could not find "
+                    + entityClass.toString()
+                    + " with primary key value "
+                    + primaryKey.toString());
+        }
+
+        return ref;
+    }
+
+    /**
+     * Synchronize the persistence context to the underlying database.
+     * 
+     * @throws PersistenceException if the flush fails
+     */
+    public void flush() {
+        checkClosed();
+
         try {
             context.commitChanges();
         }
@@ -86,28 +193,96 @@
         }
     }
 
-    @Override
-    protected void refreshInternal(Object entity) {
+    /**
+     * Set the flush mode that applies to all objects contained in the persistence
+     * context.
+     * 
+     * @param flushMode
+     */
+    public void setFlushMode(FlushModeType flushMode) {
+        checkClosed();
+
+        this.flushMode = flushMode;
+    }
+
+    /**
+     * Get the flush mode that applies to all objects contained in the persistence
+     * context.
+     * 
+     * @return flushMode
+     */
+    public FlushModeType getFlushMode() {
+        checkClosed();
+
+        return flushMode;
+    }
+
+    /**
+     * Refresh the state of the instance from the database, overwriting changes made to
+     * the entity, if any.
+     * 
+     * @param entity
+     * @throws IllegalArgumentException if not an entity or entity is not managed
+     * @throws EntityNotFoundException if the entity no longer exists in the database
+     */
+    public void refresh(Object entity) {
+        checkClosed();
         // TODO: Andrus, 2/10/2006 - implement
         throw new UnsupportedOperationException("TODO");
     }
 
-    @Override
-    protected boolean containsInternal(Object entity) {
+    /**
+     * Clear the persistence context, causing all managed entities to become detached.
+     * Changes made to entities that have not been flushed to the database will not be
+     * persisted.
+     */
+    public void clear() {
+        checkClosed();
+        // TODO: Andrus, 2/10/2006 - implement
+        throw new UnsupportedOperationException("TODO");
+    }
+
+    /**
+     * Check if the instance belongs to the current persistence context.
+     * 
+     * @throws IllegalArgumentException if not an entity
+     */
+    public boolean contains(Object entity) {
+        checkClosed();
         checkEntityType(entity);
 
         Persistent p = (Persistent) entity;
         return p.getObjectContext() == context;
     }
 
-    @Override
+    /**
+     * Create an instance of Query for executing an EJB QL statement.
+     * 
+     * @param ejbqlString an EJB QL query string
+     * @return the new query instance
+     * @throws IllegalArgumentException if query string is not valid
+     */
+    public Query createQuery(String ejbqlString) {
+        checkClosed();
+
+        // TODO: Andrus, 2/10/2006 - implement
+        throw new UnsupportedOperationException("TODO");
+    }
+
+    /**
+     * Create an instance of Query for executing a named query (in EJB QL or native SQL).
+     * 
+     * @param name the name of a query defined in metadata
+     * @return the new query instance
+     * @throws IllegalArgumentException if a query has not been defined with the given
+     *             name
+     */
     public Query createNamedQuery(String name) {
         checkClosed();
 
         return new JpaQuery(context, name);
     }
 
-    @Override
     public Query createNativeQuery(String sqlString, Class resultClass) {
         checkClosed();
         checkEntityType(resultClass);
@@ -115,25 +290,72 @@
         return new JpaNativeQuery(context, sqlString, resultClass);
     }
 
-    @Override
+    /**
+     * Create an instance of Query for executing a native SQL statement, e.g., for update
+     * or delete.
+     * 
+     * @param sqlString a native SQL query string
+     * @return the new query instance
+     */
     public Query createNativeQuery(String sqlString) {
         checkClosed();
 
-        return new JpaNativeQuery(context, sqlString, getPersistenceUnitInfo()
+        return new JpaNativeQuery(context, sqlString, factory
+                .getPersistenceUnitInfo()
                 .getPersistenceUnitName());
     }
 
-    @Override
+    /**
+     * Create an instance of Query for executing a native SQL query.
+     * 
+     * @param sqlString a native SQL query string
+     * @param resultSetMapping the name of the result set mapping
+     * @return the new query instance
+     */
+    public Query createNativeQuery(String sqlString, String resultSetMapping) {
+        checkClosed();
+
+        // TODO: Andrus, 2/10/2006 - implement
+        throw new UnsupportedOperationException("TODO");
+    }
+
+    /**
+     * Indicates to the EntityManager that a JTA transaction is active. This method should
+     * be called on a JTA application managed EntityManager that was created outside the
+     * scope of the active transaction to associate it with the current JTA transaction.
+     * <p>
+     * This implementation throws a JpaProviderException, as it only supports
+     * resource-local operation.
+     * 
+     * @throws JpaProviderException as this impementation only supports resource-local
+     *             operation.
+     */
     public void joinTransaction() {
-        // TODO: andrus, 7/24/2006 - noop
+        throw new JpaProviderException(
+                "'joinTransaction' is called on a RESOURCE_LOCAL EntityManager");
     }
 
-    @Override
     public void lock(Object entity, LockModeType lockMode) {
         // TODO: andrus, 8/15/2006 - noop
     }
 
     /**
+     * Return the resource-level transaction object. The EntityTransaction instance may be
+     * used serially to begin and commit multiple transactions.
+     * 
+     * @return EntityTransaction instance
+     */
+    public EntityTransaction getTransaction() { // note - allowed to be called on a closed
+        if (transaction == null) {
+            this.transaction = new JpaTransaction(
+                    Transaction.internalTransaction(null),
+                    this);
+        }
+
+        return transaction;
+    }
+
+    /**
      * Checks if an entity is attached to the current EntityManager, throwing
      * IllegalArgumentException if not.
      */
@@ -184,8 +406,14 @@
             throw new IllegalArgumentException("entity must be Persistent: " + className);
         }
     }
-    
-    protected void checkIdType(Class entityClass, Object id) {
-        
+
+    /**
+     * Throws an exception if called on closed factory.
+     */
+    protected void checkClosed() throws IllegalStateException {
+        if (!isOpen()) {
+            throw new IllegalStateException(
+                    "An attempt to access closed EntityManagerFactory.");
+        }
     }
 }

Copied: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactory.java (from r503214, cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JpaEntityManagerFactory.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactory.java?view=diff&rev=503390&p1=cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JpaEntityManagerFactory.java&r1=503214&p2=cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactory.java&r2=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/JpaEntityManagerFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactory.java Sun Feb  4 03:31:14 2007
@@ -29,23 +29,38 @@
 import org.apache.cayenne.access.DataDomain;
 
 /**
- * A base implementation of a Cyenne EntityManagerFactory.
+ * A Cayenne EntityManagerFactory that supports resource-local transactions.
  * 
  * @author Andrus Adamchik
  */
-public class JpaEntityManagerFactory implements EntityManagerFactory {
+public class ResourceLocalEntityManagerFactory implements EntityManagerFactory {
 
     protected DataDomain domain;
     protected boolean open;
     protected PersistenceUnitInfo unitInfo;
-    protected Object delegate;
+    protected Provider provider;
 
-    public JpaEntityManagerFactory(DataDomain domain, PersistenceUnitInfo unitInfo) {
+    /**
+     * Non-public constructor used mostly for unit testing.
+     */
+    ResourceLocalEntityManagerFactory(PersistenceUnitInfo unitInfo) {
+        this(null, null, unitInfo);
+    }
+
+    /**
+     * Creates a new JpaEntityManagerFactory.
+     */
+    public ResourceLocalEntityManagerFactory(Provider provider, DataDomain domain,
+            PersistenceUnitInfo unitInfo) {
         this.unitInfo = unitInfo;
         this.open = true;
         this.domain = domain;
+        this.provider = provider;
     }
 
+    /**
+     * Returns wrapped unit.
+     */
     protected PersistenceUnitInfo getPersistenceUnitInfo() {
         return unitInfo;
     }
@@ -86,16 +101,17 @@
      * 
      * @return a new EntityManager instance.
      */
-    public EntityManager createEntityManager(Map parameters) {
+    public EntityManager createEntityManager(Map map) {
         checkClosed();
-        return createEntityManagerInternal(parameters);
+        return createEntityManagerInternal(map);
     }
 
-    protected EntityManager createEntityManagerInternal(Map parameters) {
-        ResourceLocalEntityManager manager = new ResourceLocalEntityManager(domain
-                .createDataContext(), this, parameters);
-        manager.setDelegate(getDelegate());
-        return manager;
+    /**
+     * Creates a new resource-local EntityManager. Parameter map is ignored as Cayenne
+     * provider defines no properties for EntityManager as of now.
+     */
+    protected EntityManager createEntityManagerInternal(Map map) {
+        return new ResourceLocalEntityManager(domain.createDataContext(), this);
     }
 
     /**
@@ -109,17 +125,10 @@
     }
 
     /**
-     * Returns a "delegate" object which is usually a parent persistence provider.
-     */
-    public Object getDelegate() {
-        return delegate;
-    }
-
-    /**
-     * Sets a "delegate" object which is usually a parent persistence provider.
+     * Returns a parent persistence provider.
      */
-    public void setDelegate(Object delegate) {
-        this.delegate = delegate;
+    public Provider getProvider() {
+        return provider;
     }
 
     /**

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/DefaultDataSourceFactory.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/DefaultDataSourceFactory.java?view=diff&rev=503390&r1=503389&r2=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/DefaultDataSourceFactory.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/DefaultDataSourceFactory.java Sun Feb  4 03:31:14 2007
@@ -39,7 +39,7 @@
  * provider-specific properties. If such properties are not present, a DataSource is
  * obtained via JNDI.
  * <p>
- * Properties are specified in the correspondign section of the <em>persistence.xml</em>
+ * Properties are specified in the corresponding section of the <em>persistence.xml</em>
  * file. All property names related to a given named DataSource must be prefixed with
  * <em>"CayenneDataSource.[datasource name]."</em>. The following properties are
  * supported:

Modified: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/JpaUnit.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/JpaUnit.java?view=diff&rev=503390&r1=503389&r2=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/JpaUnit.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/main/java/org/apache/cayenne/jpa/conf/JpaUnit.java Sun Feb  4 03:31:14 2007
@@ -43,9 +43,6 @@
  */
 public class JpaUnit implements PersistenceUnitInfo {
 
-    // spec defaults
-    static final PersistenceUnitTransactionType DEFAULT_TRANSACTION_TYPE = PersistenceUnitTransactionType.JTA;
-
     protected String persistenceUnitName;
     protected List<String> mappingFileNames;
     protected List<URL> jarFileUrls;
@@ -107,9 +104,13 @@
 
     public PersistenceUnitTransactionType getTransactionType() {
         String type = getProperty(Provider.TRANSACTION_TYPE_PROPERTY);
+
+        // default JTA type is somewhat arbitrary as application-managed EntityManagers
+        // will use resource-local, while container-managed will use JTA. Normally whoever
+        // created this unit will set the right value.
         return type != null
                 ? PersistenceUnitTransactionType.valueOf(type)
-                : DEFAULT_TRANSACTION_TYPE;
+                : PersistenceUnitTransactionType.JTA;
     }
 
     String getProperty(String key) {

Added: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/MockObjectContext.java
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/MockObjectContext.java?view=auto&rev=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/MockObjectContext.java (added)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/MockObjectContext.java Sun Feb  4 03:31:14 2007
@@ -0,0 +1,112 @@
+/*****************************************************************
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ ****************************************************************/
+package org.apache.cayenne.jpa;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.cayenne.DataChannel;
+import org.apache.cayenne.DeleteDenyException;
+import org.apache.cayenne.ObjectContext;
+import org.apache.cayenne.ObjectId;
+import org.apache.cayenne.Persistent;
+import org.apache.cayenne.QueryResponse;
+import org.apache.cayenne.graph.GraphManager;
+import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.query.Query;
+
+
+public class MockObjectContext implements ObjectContext {
+
+    public void commitChanges() {
+    }
+
+    public void commitChangesToParent() {
+    }
+
+    public void deleteObject(Object object) throws DeleteDenyException {
+    }
+
+    public Collection deletedObjects() {
+        return null;
+    }
+
+    public DataChannel getChannel() {
+        return null;
+    }
+
+    public EntityResolver getEntityResolver() {
+        return null;
+    }
+
+    public GraphManager getGraphManager() {
+        return null;
+    }
+
+    public Persistent localObject(ObjectId id, Object prototype) {
+        return null;
+    }
+
+    public Collection modifiedObjects() {
+        return null;
+    }
+
+    public Persistent newObject(Class persistentClass) {
+        return null;
+    }
+
+    public Collection newObjects() {
+        return null;
+    }
+
+    public QueryResponse performGenericQuery(Query query) {
+        return null;
+    }
+
+    public List performQuery(Query query) {
+        return null;
+    }
+
+    public void prepareForAccess(Persistent object, String property) {
+    }
+
+    public void prepareForAccess(Persistent object, String property, boolean lazyFaulting) {
+    }
+
+    public void propertyChanged(
+            Persistent object,
+            String property,
+            Object oldValue,
+            Object newValue) {
+    }
+
+    public void registerNewObject(Object object) {
+    }
+
+    public void rollbackChanges() {
+    }
+
+    public void rollbackChangesLocally() {
+    }
+
+    public Collection uncommittedObjects() {
+        return null;
+    }
+
+}

Copied: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactoryTest.java (from r503207, cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerFactoryTest.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactoryTest.java?view=diff&rev=503390&p1=cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerFactoryTest.java&r1=503207&p2=cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactoryTest.java&r2=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerFactoryTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerFactoryTest.java Sun Feb  4 03:31:14 2007
@@ -23,11 +23,10 @@
 
 import junit.framework.TestCase;
 
-public class JpaEntityManagerFactoryTest extends TestCase {
+public class ResourceLocalEntityManagerFactoryTest extends TestCase {
 
     public void testOpenClose() {
-        JpaEntityManagerFactory f = new JpaEntityManagerFactory(
-                null,
+        ResourceLocalEntityManagerFactory f = new ResourceLocalEntityManagerFactory(
                 new MockPersistenceUnitInfo());
         assertTrue(f.isOpen());
 

Copied: cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerTest.java (from r503207, cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerTest.java)
URL: http://svn.apache.org/viewvc/cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerTest.java?view=diff&rev=503390&p1=cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerTest.java&r1=503207&p2=cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerTest.java&r2=503390
==============================================================================
--- cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/JpaEntityManagerTest.java (original)
+++ cayenne/main/trunk/framework/cayenne-jpa-unpublished/src/test/java/org/apache/cayenne/jpa/ResourceLocalEntityManagerTest.java Sun Feb  4 03:31:14 2007
@@ -24,11 +24,10 @@
 
 import junit.framework.TestCase;
 
-public class JpaEntityManagerTest extends TestCase {
+public class ResourceLocalEntityManagerTest extends TestCase {
 
     public void testOpenClose() throws Exception {
-        JpaEntityManagerFactory factory = new JpaEntityManagerFactory(
-                null,
+        ResourceLocalEntityManagerFactory factory = new ResourceLocalEntityManagerFactory(
                 new MockPersistenceUnitInfo()) {
 
             @Override
@@ -36,24 +35,28 @@
                 return true;
             }
         };
-        JpaEntityManager m = new MockJpaEntityManager(factory) {
+
+        final EntityTransaction tx = new MockEntityTransaction() {
 
             @Override
-            protected EntityTransaction createResourceLocalTransaction() {
-                return new MockEntityTransaction() {
+            public boolean isActive() {
+                return true;
+            }
+        };
 
-                    @Override
-                    public boolean isActive() {
-                        return true;
-                    }
-                };
+        ResourceLocalEntityManager m = new ResourceLocalEntityManager(
+                new MockObjectContext(),
+                factory) {
+
+            @Override
+            public EntityTransaction getTransaction() {
+                this.transaction = tx;
+                return tx;
             }
         };
 
         assertTrue(m.isOpen());
-
         m.close();
-
         assertFalse(m.isOpen());
 
         // check that all methods throw ... or at least some :-)
@@ -99,8 +102,7 @@
     }
 
     public void testCloseActiveTransactionInProgress() {
-        JpaEntityManagerFactory factory = new JpaEntityManagerFactory(
-                null,
+        ResourceLocalEntityManagerFactory factory = new ResourceLocalEntityManagerFactory(
                 new MockPersistenceUnitInfo()) {
 
             @Override
@@ -109,17 +111,22 @@
             }
         };
 
-        JpaEntityManager m = new MockJpaEntityManager(factory) {
+        final EntityTransaction tx = new MockEntityTransaction() {
 
             @Override
-            protected EntityTransaction createResourceLocalTransaction() {
-                return new MockEntityTransaction() {
+            public boolean isActive() {
+                return true;
+            }
+        };
+
+        ResourceLocalEntityManager m = new ResourceLocalEntityManager(
+                new MockObjectContext(),
+                factory) {
 
-                    @Override
-                    public boolean isActive() {
-                        return true;
-                    }
-                };
+            @Override
+            public EntityTransaction getTransaction() {
+                this.transaction = tx;
+                return tx;
             }
         };
 
@@ -140,8 +147,7 @@
     public void testCloseFactoryClosed() {
         final boolean[] factoryCloseState = new boolean[1];
 
-        JpaEntityManagerFactory factory = new JpaEntityManagerFactory(
-                null,
+        ResourceLocalEntityManagerFactory factory = new ResourceLocalEntityManagerFactory(
                 new MockPersistenceUnitInfo()) {
 
             @Override
@@ -150,7 +156,9 @@
             }
         };
 
-        JpaEntityManager m = new MockJpaEntityManager(factory);
+        ResourceLocalEntityManager m = new ResourceLocalEntityManager(
+                new MockObjectContext(),
+                factory);
 
         assertTrue(m.isOpen());
         factoryCloseState[0] = true;



Mime
View raw message