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/01/15 14:08:42 UTC

svn commit: r899618 - in /incubator/aries/trunk/jpa/jpa-container-context: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/aries/ src/main/java/org/apache/aries/jpa/ src/main/java/org/apache/aries/...

Author: timothyjward
Date: Fri Jan 15 13:08:41 2010
New Revision: 899618

URL: http://svn.apache.org/viewvc?rev=899618&view=rev
Log: (empty)

Added:
    incubator/aries/trunk/jpa/jpa-container-context/
    incubator/aries/trunk/jpa/jpa-container-context/pom.xml
    incubator/aries/trunk/jpa/jpa-container-context/src/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/
    incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAPersistenceContextRegistry.java

Added: incubator/aries/trunk/jpa/jpa-container-context/pom.xml
URL: http://svn.apache.org/viewvc/incubator/aries/trunk/jpa/jpa-container-context/pom.xml?rev=899618&view=auto
==============================================================================
--- incubator/aries/trunk/jpa/jpa-container-context/pom.xml (added)
+++ incubator/aries/trunk/jpa/jpa-container-context/pom.xml Fri Jan 15 13:08:41 2010
@@ -0,0 +1,59 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <parent>
+    <artifactId>jpa</artifactId>
+    <groupId>org.apache.aries.jpa</groupId>
+    <version>1.0.0-incubating-SNAPSHOT</version>
+  </parent>
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.aries.jpa</groupId>
+  <artifactId>jpa-container-context</artifactId>
+  <name>Aries JPA Container Managed Contexts</name>
+  <packaging>bundle</packaging>
+  <version>1.0.0-incubating-SNAPSHOT</version>
+  
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jpa_2.0_spec</artifactId>
+      <version>1.0-SNAPSHOT</version>
+    </dependency> 
+    <dependency>
+      <groupId>org.apache.geronimo.specs</groupId>
+      <artifactId>geronimo-jta_1.1_spec</artifactId>
+      <version>1.1.1</version> 
+    </dependency> 
+  </dependencies>
+  
+  
+      <build>
+       <resources>
+            <resource>
+                <targetPath>OSGI-INF/blueprint</targetPath>
+                <filtering>false</filtering>
+                <directory>${basedir}/src/main/resources/OSGI-INF/blueprint</directory>
+                <includes>
+                    <include>*.xml</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${pom.groupId}.container</Bundle-SymbolicName>
+                        <Export-Package>
+                            org.apache.aries.jpa.container.parsing;version="${pom.version}",
+                            org.apache.aries.jpa.container;version="${pom.version}"
+                        </Export-Package>
+                        <_versionpolicy>[$(version;==;$(@)),$(version;+;$(@)))</_versionpolicy>
+                        <_removeheaders>Ignore-Package,Include-Resource,Private-Package,Bundle-DocURL</_removeheaders>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+  
+</project>
\ No newline at end of file

Added: incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAPersistenceContextRegistry.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/JTAPersistenceContextRegistry.java?rev=899618&view=auto
==============================================================================
--- incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAPersistenceContextRegistry.java (added)
+++ incubator/aries/trunk/jpa/jpa-container-context/src/main/java/org/apache/aries/jpa/container/context/transaction/impl/JTAPersistenceContextRegistry.java Fri Jan 15 13:08:41 2010
@@ -0,0 +1,102 @@
+package org.apache.aries.jpa.container.context.transaction.impl;
+
+import java.util.IdentityHashMap;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import javax.persistence.EntityManager;
+import javax.persistence.EntityManagerFactory;
+import javax.persistence.TransactionRequiredException;
+import javax.transaction.Synchronization;
+import javax.transaction.TransactionSynchronizationRegistry;
+
+/**
+ * This class is used to manage the lifecycle of JTA peristence contexts
+ */
+public class JTAPersistenceContextRegistry {
+
+  /** 
+   * The transaction synchronization registry, used to determine the currently
+   * active transaction, and to register for post-commit cleanup. 
+   */
+  private TransactionSynchronizationRegistry tranRegistry;
+
+  /**
+   * The registry of active persistence contexts. The outer map must be thread safe, as
+   * multiple threads can request persistence contexts. The inner Map does not need to
+   * be thread safe as only one thread can be in a transaction. As a result the inner
+   * Map will never be accessed concurrently.
+   */
+  private final ConcurrentMap<Object, Map<EntityManagerFactory, EntityManager>> persistenceContextRegistry = new ConcurrentHashMap<Object, Map<EntityManagerFactory,EntityManager>>();
+  
+  /**
+   * Get a PersistenceContext for the current transaction. The persistence context will 
+   * automatically be closed when the transaction completes.
+   * 
+   * @param persistenceUnit The peristence unit to create the persitence context from
+   * @param properties  Any properties that should be passed on the call to {@code createEntityManager()}
+   * 
+   * @return A persistence context associated with the current transaction. Note that this will
+   *         need to be wrappered to obey the JPA spec by throwing the correct exceptions
+   * @throws {@link TransactionRequiredException} if there is no active transaction.
+   */
+  public EntityManager getCurrentPersistenceContext(EntityManagerFactory persistenceUnit, Map<?,?> properties)
+  {
+    //There will only ever be one thread associated with a transaction at a given time
+    //As a result, it is only the outer map that needs to be thread safe.
+    Object transactionKey = tranRegistry.getTransactionKey();
+    
+    //TODO Globalize and log this problem
+    //Throw the error on to the client
+    if(transactionKey == null)
+      throw new TransactionRequiredException();
+    
+    //Get hold of the Map. If there is no Map already registered then add one.
+    //We don't need to worry about a race condition, as no other thread will
+    //share our transaction
+    Map<EntityManagerFactory, EntityManager> contextsForTransaction = persistenceContextRegistry.get(transactionKey);
+    
+    //If we need to, create a new Map add it to the registry, and register it for cleanup
+    if(contextsForTransaction == null) {
+      contextsForTransaction = new IdentityHashMap<EntityManagerFactory, EntityManager>();
+      persistenceContextRegistry.put(transactionKey, contextsForTransaction);
+      tranRegistry.registerInterposedSynchronization(new EntityManagerClearUp(transactionKey));
+    }
+    
+    //Still only one thread for this transaction, so don't worry about any race conditions
+    EntityManager toReturn = contextsForTransaction.get(persistenceUnit);
+    
+    if(toReturn == null) {
+      toReturn = (properties == null) ? persistenceUnit.createEntityManager() : persistenceUnit.createEntityManager(properties);
+      contextsForTransaction.put(persistenceUnit, toReturn);
+    }
+    
+    return toReturn;
+  }
+
+  /**
+   * This class is used to close EntityManager instances once the transaction has committed,
+   * and clear the persistenceContextRegistry of old persistence contexts.
+   */
+  private class EntityManagerClearUp implements Synchronization {
+
+    private final Object key;
+    
+    public EntityManagerClearUp(Object transactionKey) {
+      key = transactionKey;
+    }
+    
+    public void afterCompletion(int arg0) {
+      Map<EntityManagerFactory, EntityManager> tidyUp = persistenceContextRegistry.remove(key);
+      if(tidyUp != null) {
+        for(EntityManager em : tidyUp.values())
+          em.close();
+      }
+    }
+
+    public void beforeCompletion() {
+      //This is a no-op;
+    }
+  }
+}