osdir.com

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[jira] [Commented] (ARIES-1783) TransactionRequiredException when non-transactional method precedes a transactional one in the same service.


    [ https://issues.apache.org/jira/browse/ARIES-1783?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16699161#comment-16699161 ] 

ASF GitHub Bot commented on ARIES-1783:
---------------------------------------

cschneider closed pull request #3: ARIES-1783 EM joins transaction when needed
URL: https://github.com/apache/aries-jpa/pull/3
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/container/itest/bundle/blueprint/impl/CarServiceWithRequiresNew.java b/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/container/itest/bundle/blueprint/impl/CarServiceWithRequiresNew.java
index d1b041c..754bdd8 100644
--- a/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/container/itest/bundle/blueprint/impl/CarServiceWithRequiresNew.java
+++ b/itests/jpa-container-blueprint-testbundle/src/main/java/org/apache/aries/jpa/container/itest/bundle/blueprint/impl/CarServiceWithRequiresNew.java
@@ -17,6 +17,7 @@
 
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.List;
 
 import javax.transaction.Transactional;
 import javax.transaction.Transactional.TxType;
@@ -53,7 +54,9 @@ public void addCar(Car car) {
             ref = getService();
             CarService carService = bundleContext.getService(ref);
             carService.addCar(c);
-            return Arrays.asList(this.getCar("TR123"));
+            final List<Car> returnVal = Arrays.asList(this.getCar("TR123"));
+            carService.deleteCar("TR123");
+            return returnVal;
         } finally {
             if (ref != null) {
                 bundleContext.ungetService(ref);
@@ -75,7 +78,9 @@ public void updateCar(Car car) {
     }
 
     @Override
+    @Transactional
     public void deleteCar(String id) {
+        em.remove(this.getCar(id));
     }
 
     public void setBundleContext(BundleContext bundleContext) {
diff --git a/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintTest.java b/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintTest.java
index 507ff3e..ab516c4 100644
--- a/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintTest.java
+++ b/itests/jpa-container-itest/src/test/java/org/apache/aries/jpa/blueprint/aries/itest/BlueprintTest.java
@@ -43,10 +43,10 @@
 public class BlueprintTest extends AbstractCarJPAITest {
     @Inject
     Coordinator coordinator;
-    
+
     @Inject
     UserTransaction ut;
-    
+
     @Test
     public void testCoordination() {
         assertNoCoordination();
@@ -66,7 +66,7 @@ public void testCoordination() {
             Assert.assertEquals(0, carService.getCars().size());
         }
     }
-    
+
     @Test
     public void testInjectToMethod() throws Exception {
         carLifecycle(getCarService("method"));
@@ -86,7 +86,7 @@ public void testEmf() throws Exception {
     public void testEm() throws Exception {
         carLifecycle(getCarService("em"));
     }
-    
+
     @Test
     public void testEmJtaAnn() throws Exception {
         carLifecycle(getCarService("emJtaAnn"));
@@ -96,17 +96,17 @@ public void testEmJtaAnn() throws Exception {
     public void testSupplier() throws Exception {
         carLifecycle(getCarService("supplier"));
     }
-    
+
     @Test
     public void testRealTransactional() throws Exception {
         carRealTransactionalLifecycle(getCarService("emJtaAnn"));
     }
-    
+
     @Test
     public void testInlined() throws Exception {
         carRealTransactionalLifecycle(getCarService("emJtaAnnInlined"));
     }
-    
+
     @Test
     public void testCoordinationLifecycle() throws InterruptedException, ExecutionException {
         CarService carService = getCarService("em");
@@ -127,7 +127,6 @@ public void testCoordinationLifecycle() throws InterruptedException, ExecutionEx
     }
 
     @Test
-    @Ignore
     public void testCarWithRequiresNewAnnotation() throws Exception {
         CarService cs = getCarService("rn");
         cs.getCars();
@@ -146,7 +145,7 @@ private void carLifecycle(CarService carService) {
         assertBlueCar(carService.getCar(BLUE_PLATE));
         carService.deleteCar(BLUE_PLATE);
     }
-    
+
     private void carRealTransactionalLifecycle(CarService carService) throws IllegalStateException, SystemException, NotSupportedException {
         assertNoCoordination();
         if (carService.getCar(BLACK_CAR_PLATE) != null) {
@@ -162,7 +161,7 @@ private void assertNoCoordination() {
         Coordination coord = coordinator.peek();
         Assert.assertNull("There should not be a coordination on this thread", coord);
     }
-    
+
     private void assertNoCars(CarService carService) {
         Assert.assertEquals("Invalid number of cars", 0, carService.getCars().size());
     }
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 14577e6..1956f01 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
@@ -29,8 +29,16 @@
 
 import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
 
 import org.apache.aries.jpa.supplier.EmSupplier;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
 import org.osgi.service.coordinator.Coordination;
 import org.osgi.service.coordinator.Coordinator;
 import org.osgi.service.coordinator.Participant;
@@ -39,7 +47,7 @@
 
 /**
  * Thread safe way to use an EntityManager.
- * 
+ *
  * Before the EMF is closed the close() method has to be called to make
  * sure all EMs are closed.
  */
@@ -88,9 +96,26 @@ public EntityManager get() {
             setEm(coordination, em);
             coordination.addParticipant(new EmShutDownParticipant());
         }
+        else {
+            final Bundle bundle = FrameworkUtil.getBundle(this.getClass());
+            if (bundle != null) {
+                final BundleContext bundleContext = bundle.getBundleContext();
+                ServiceReference<TransactionManager> tmRef = bundleContext.getServiceReference(TransactionManager.class);
+                TransactionManager tm = bundleContext.getService(tmRef);
+                try {
+                    final Transaction transaction = tm.getTransaction();
+                    if (transaction != null && transaction.getStatus() == Status.STATUS_ACTIVE) {
+                        em.joinTransaction();
+                    }
+                }
+                catch( SystemException se ) {
+                    throw new IllegalStateException("Unable to check transaction status and join the transaction", se);
+                }
+            }
+        }
         return em;
     }
-    
+
     Coordination getTopCoordination() {
         Coordination coordination = coordinator.peek();
         while (coordination != null && coordination.getEnclosingCoordination() != null) {
@@ -98,7 +123,7 @@ Coordination getTopCoordination() {
         }
         return coordination;
     }
-    
+
     private void setEm(Coordination coordination, EntityManager em) {
         Map<Class<?>, Object> vars = coordination.getVariables();
         synchronized (vars) {
@@ -126,7 +151,7 @@ private EntityManager removeEm(Coordination coordination) {
         }
     }
 
-    
+
     @SuppressWarnings("unchecked")
     private Map<String, EntityManager> getEmMap(Coordination coordination) {
         Map<String, EntityManager> emMap = (Map<String, EntityManager>)coordination.getVariables().get(EntityManager.class);
@@ -167,7 +192,7 @@ public boolean close() {
     }
 
     private synchronized boolean shutdownRemaining() {
-        boolean clean = emSet.isEmpty(); 
+        boolean clean = emSet.isEmpty();
         if  (!clean) {
             LOG.warn("{} EntityManagers still open after timeout. Shutting them down now", emSet.size());
         }
@@ -206,7 +231,7 @@ public void ended(Coordination coordination) throws Exception {
             EntityManager em = removeEm(coordination);
             emSet.remove(em);
             em.close();
-            
+
             if (shutdown.get()) {
                 emsToShutDown.countDown();
             }


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@xxxxxxxxxxxxxxxx


> TransactionRequiredException when non-transactional method precedes a transactional one in the same service.
> ------------------------------------------------------------------------------------------------------------
>
>                 Key: ARIES-1783
>                 URL: https://issues.apache.org/jira/browse/ARIES-1783
>             Project: Aries
>          Issue Type: Bug
>          Components: JPA
>    Affects Versions: jpa-2.5.0
>            Reporter: Daniel Estermann
>            Assignee: Christian Schneider
>            Priority: Major
>
> Assume I have a service implementation with a method annotated with @Transactional and one of TxTypes not starting a transaction:
>  * NEVER
>  * NOT_SUPPORTED
>  * SUPPORTS
> From that non-transactional method I want to use a self-reference resolved via BundleContext to call a transactional method in the same service, annotated with one of those TxTypes:
>  * REQUIRED
>  * REQURES_NEW
> Since the resolved self-reference is a proxied object I expect it to be able to start a new transaction. This is not the case however and the subject exception occurs.
>  
> I created a test case revealing the issue in the following pull request: https://github.com/apache/aries-jpa/pull/2



--
This message was sent by Atlassian JIRA
(v7.6.3#76005)