[ARIES-1346] Hold a reference to coordination to avoid it to be considered ORPHANED

git-svn-id: https://svn.apache.org/repos/asf/aries/trunk/jpa@1694015 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/itests/jpa-container-itest/pom.xml b/itests/jpa-container-itest/pom.xml
index 078f6b2..8da6113 100644
--- a/itests/jpa-container-itest/pom.xml
+++ b/itests/jpa-container-itest/pom.xml
@@ -49,9 +49,9 @@
             <version>5.0.0</version>
         </dependency>
         <dependency>
-            <groupId>org.eclipse.equinox</groupId>
-            <artifactId>org.eclipse.equinox.coordinator</artifactId>
-            <version>1.1.0.v20120522-1841</version>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.coordinator</artifactId>
+            <version>1.0.0</version>
             <scope>test</scope>
         </dependency>
         <dependency>
diff --git a/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java b/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java
index 529b8fd..b05a5da 100644
--- a/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java
+++ b/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerTest.java
@@ -21,6 +21,7 @@
 import java.util.List;
 import java.util.Map;
 
+import javax.inject.Inject;
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
 import javax.persistence.Query;
@@ -30,9 +31,13 @@
 import org.apache.aries.jpa.itest.AbstractCarJPAITest;
 import org.apache.aries.jpa.supplier.EmSupplier;
 import org.junit.Test;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Coordinator;
 import org.osgi.service.jpa.EntityManagerFactoryBuilder;
 
 public abstract class JPAContainerTest extends AbstractCarJPAITest {
+    @Inject
+    Coordinator coordinator;
 
     @Test
     public void testCarEMFBuilder() throws Exception {
@@ -71,8 +76,8 @@
     @Test
     public void testEmSupplier() throws Exception {
         EmSupplier emSupplier = getService(EmSupplier.class, "(osgi.unit.name=" + XA_TEST_UNIT + ")");
+        Coordination coordination = coordinator.begin("test", 0);
         try {
-            emSupplier.preCall();
             EntityManager em = emSupplier.get();
             carLifecycleXA(ut, em);
 
@@ -110,7 +115,7 @@
 
             cleanup(em);
         } finally {
-            emSupplier.postCall();
+            coordination.end();
         }
     }
 
diff --git a/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/itest/AbstractJPAItest.java b/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/itest/AbstractJPAItest.java
index c122df1..3c6eda4 100644
--- a/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/itest/AbstractJPAItest.java
+++ b/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/itest/AbstractJPAItest.java
@@ -185,7 +185,7 @@
 
                              mvnBundle("org.ow2.asm", "asm-all"),
                              mvnBundle("org.apache.felix", "org.apache.felix.configadmin"),
-                             mvnBundle("org.eclipse.equinox", "org.eclipse.equinox.coordinator"),
+                             mvnBundle("org.apache.felix", "org.apache.felix.coordinator"),
 
                              mvnBundle("org.apache.aries.proxy", "org.apache.aries.proxy.api"),
                              mvnBundle("org.apache.aries.proxy", "org.apache.aries.proxy.impl"),
diff --git a/jpa-api/src/main/java/org/apache/aries/jpa/supplier/EmSupplier.java b/jpa-api/src/main/java/org/apache/aries/jpa/supplier/EmSupplier.java
index 9d534e3..3613c50 100644
--- a/jpa-api/src/main/java/org/apache/aries/jpa/supplier/EmSupplier.java
+++ b/jpa-api/src/main/java/org/apache/aries/jpa/supplier/EmSupplier.java
@@ -30,13 +30,17 @@
 
     /**
      * Is called before first access to get() in a method
+     * @deprecated Use a Coordination instead
      */
+    @Deprecated
     void preCall();
     
     EntityManager get();
 
     /**
      * Is called after last access to get() in a method
+     * @deprecated Use a Coordination instead
      */
+    @Deprecated
     void postCall();
 }
diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JPAParticipant.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JPAParticipant.java
new file mode 100644
index 0000000..bdd56ac
--- /dev/null
+++ b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JPAParticipant.java
@@ -0,0 +1,50 @@
+/*
+ * 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.aries.jpa.blueprint.impl;
+
+import javax.persistence.EntityManager;
+
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Participant;
+
+final class JPAParticipant implements Participant {
+    private final EntityManager em;
+
+    JPAParticipant(EntityManager em) {
+        this.em = em;
+    }
+
+    @Override
+    public void failed(Coordination coordination) throws Exception {
+        em.getTransaction().setRollbackOnly();
+    }
+
+    @Override
+    public void ended(Coordination coordination) throws Exception {
+        if (em.getTransaction().getRollbackOnly()) {
+            try {
+                em.getTransaction().rollback();
+             } catch (Exception e1) {
+                 // Ignore
+             }
+        } else {
+            em.getTransaction().commit();
+        }
+    }
+}
\ No newline at end of file
diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java
index ee67cc0..d9071cb 100644
--- a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java
+++ b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaBeanProcessor.java
@@ -44,6 +44,7 @@
 import org.osgi.framework.BundleContext;

 import org.osgi.framework.FrameworkUtil;

 import org.osgi.service.blueprint.reflect.BeanMetadata;

+import org.osgi.service.coordinator.Coordinator;

 import org.slf4j.Logger;

 import org.slf4j.LoggerFactory;

 

@@ -115,8 +116,8 @@
                 EmSupplier supplierProxy = ServiceProxy.create(context, EmSupplier.class, filter);

                 jpaAnnotatedMember.handleSupplierMember(member, pcAnn.unitName(), supplierProxy);

                 beanProxies.add((Closeable)supplierProxy);

-

-                Interceptor interceptor = new JpaInterceptor(supplierProxy);

+                Coordinator coordinator = ServiceProxy.create(context, Coordinator.class);

+                Interceptor interceptor = new JpaInterceptor(supplierProxy, coordinator);

                 cdr.registerInterceptorWithComponent(beanData, interceptor);

             } else {

                 PersistenceUnit puAnn = member.getAnnotation(PersistenceUnit.class);

diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptor.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptor.java
index 59550a5..4c155fa 100644
--- a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptor.java
+++ b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/impl/JpaInterceptor.java
@@ -26,16 +26,20 @@
 import org.apache.aries.blueprint.Interceptor;
 import org.apache.aries.jpa.supplier.EmSupplier;
 import org.osgi.service.blueprint.reflect.ComponentMetadata;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Coordinator;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class JpaInterceptor implements Interceptor {
     private static Logger LOG = LoggerFactory.getLogger(JpaInterceptor.class);
-    private EmSupplier emSupplier;
+    EmSupplier emSupplier;
     private Boolean cachedIsResourceLocal;
+    private Coordinator coordinator;
 
-    public JpaInterceptor(EmSupplier emSupplier) {
+    public JpaInterceptor(EmSupplier emSupplier, Coordinator coordinator) {
         this.emSupplier = emSupplier;
+        this.coordinator = coordinator;
     }
 
     public int getRank() {
@@ -45,13 +49,14 @@
     public Object preCall(ComponentMetadata cm, Method m, Object... parameters) throws Throwable {
         try {
             LOG.debug("PreCall for bean {}, method {}", cm.getId(), m.getName());
-            emSupplier.preCall();
-            EntityManager em = emSupplier.get();
+            Coordination coordination = coordinator.begin("jpa", 0);
+            final EntityManager em = emSupplier.get();
             boolean weControlTx = isResourceLocal(em) && !em.getTransaction().isActive();
             if (weControlTx) {
                 em.getTransaction().begin();
+                coordination.addParticipant(new JPAParticipant(em));
             }
-            return weControlTx;
+            return coordination;
         } catch (Exception e) {
             LOG.warn("Exception from EmSupplier.preCall", e);
             throw new RuntimeException(e);
@@ -60,35 +65,16 @@
 
     public void postCallWithException(ComponentMetadata cm, Method m, Throwable ex, Object preCallToken) {
         LOG.debug("PostCallWithException for bean {}, method {}", cm.getId(), m.getName(), ex);
-        boolean weControlTx = preCallToken == null ? false : (Boolean)preCallToken;
-        if (weControlTx) {
-            safeRollback(emSupplier.get(), ex);
-        }
-        try {
-            emSupplier.postCall();
-        } catch (Exception e) {
-            LOG.warn("Exception from EmSupplier.postCall", e);
-        }
+        ((Coordination) preCallToken).fail(ex);
     }
 
     public void postCallWithReturn(ComponentMetadata cm, Method m, Object returnType, Object preCallToken)
         throws Exception {
         LOG.debug("PostCallWithReturn for bean {}, method {}", cm.getId(), m.getName());
-        boolean weControlTx = preCallToken == null ? false : (Boolean)preCallToken;
-        if (weControlTx) {
-            emSupplier.get().getTransaction().commit();
-        }
-        emSupplier.postCall();
+        ((Coordination) preCallToken).end();
     }
 
-    private void safeRollback(EntityManager em, Throwable e) {
-        if (em != null) {
-            try {
-                em.getTransaction().rollback();
-            } catch (Exception e1) {
-            }
-        }
-    }
+
 
     private boolean isResourceLocal(EntityManager em) {
         if (cachedIsResourceLocal == null) {
diff --git a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/ServiceProxy.java b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/ServiceProxy.java
index 36e726d..fdacc48 100644
--- a/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/ServiceProxy.java
+++ b/jpa-blueprint/src/main/java/org/apache/aries/jpa/blueprint/supplier/impl/ServiceProxy.java
@@ -35,14 +35,16 @@
     private ServiceTracker tracker;

 

     public ServiceProxy(BundleContext context, String filterS) {

-        Filter filter;

+        tracker = new ServiceTracker<>(context, createFilter(filterS), null);

+        tracker.open();

+    }

+

+    private Filter createFilter(String filterS) {

         try {

-            filter = FrameworkUtil.createFilter(filterS);

+            return filterS == null ? null : FrameworkUtil.createFilter(filterS);

         } catch (InvalidSyntaxException e) {

             throw new IllegalStateException(e);

         }

-        tracker = new ServiceTracker<>(context, filter, null);

-        tracker.open();

     }

 

     private Object getService() {

@@ -67,6 +69,14 @@
             throw new IllegalStateException(e);

         }

     }

+    

+    public static <T> T create(BundleContext context, Class<T> iface) {

+        return  (T) create(context, iface, getFilter(iface));

+    }

+    

+    private static String getFilter(Class<?> clazz) {

+        return String.format("(objectClass=%s)", clazz.getName());

+    }

 

     @SuppressWarnings("unchecked")

     public static <T> T create(BundleContext context, Class<T> iface, String filter) {

diff --git a/jpa-support/src/main/java/org/apache/aries/jpa/support/impl/EMSupplierImpl.java b/jpa-support/src/main/java/org/apache/aries/jpa/support/impl/EMSupplierImpl.java
index 4180bd0..209a67e 100644
--- a/jpa-support/src/main/java/org/apache/aries/jpa/support/impl/EMSupplierImpl.java
+++ b/jpa-support/src/main/java/org/apache/aries/jpa/support/impl/EMSupplierImpl.java
@@ -141,17 +141,10 @@
 
     @Override
     public void preCall() {
-        coordinator.begin("jpa." + unitName, 0);
     }
 
     @Override
     public void postCall() {
-        try {
-            Coordination coord = coordinator.pop();
-            coord.end();
-        } catch (Throwable t) {
-            LOG.warn("Error ending coord", t);
-        }
     }
 
     /**
diff --git a/jpa-support/src/main/java/org/apache/aries/jpa/support/impl/XAJpaTemplate.java b/jpa-support/src/main/java/org/apache/aries/jpa/support/impl/XAJpaTemplate.java
index afe858e..d605fa6 100644
--- a/jpa-support/src/main/java/org/apache/aries/jpa/support/impl/XAJpaTemplate.java
+++ b/jpa-support/src/main/java/org/apache/aries/jpa/support/impl/XAJpaTemplate.java
@@ -53,7 +53,6 @@
         try {
             tranToken = ta.begin(tm);
             coord = coordinator.begin(this.getClass().getName(), 0);
-            emSupplier.preCall();
             em = emSupplier.get();
             em.joinTransaction();
             R result = (R)code.apply(em);