Author: rmannibucau
Date: Mon Jul 23 14:01:37 2012
New Revision: 1364638

URL: http://svn.apache.org/viewvc?rev=1364638&view=rev
Log:
clean a bit jta connection before working in a branch on it

Modified:
    
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedConnection.java
    
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedDataSource.java
    
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/LocalXAResource.java
    
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ManagedDataSourceTest.java

Modified: 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedConnection.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedConnection.java?rev=1364638&r1=1364637&r2=1364638&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedConnection.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedConnection.java
 Mon Jul 23 14:01:37 2012
@@ -3,20 +3,28 @@ package org.apache.openejb.resource.jdbc
 import org.apache.openejb.OpenEJB;
 import org.apache.openejb.resource.jdbc.managed.local.LocalXAResource;
 
+import javax.transaction.RollbackException;
 import javax.transaction.Status;
 import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
 import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 import javax.transaction.xa.XAResource;
 import java.lang.reflect.InvocationHandler;
+import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.sql.Connection;
 import java.sql.SQLException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 public class ManagedConnection implements InvocationHandler {
-    protected final Connection delegate;
-    protected final XAResource xaResource;
-    private boolean previousAutoCommit;
+    private static final Map<Transaction, Connection> CONNECTION_BY_TX = new 
ConcurrentHashMap<Transaction, Connection>();
+
+    protected Connection delegate;
+    protected XAResource xaResource;
+
+    private Transaction currentTransaction;
 
     protected ManagedConnection(final Connection connection, final XAResource 
resource) {
         delegate = connection;
@@ -29,37 +37,91 @@ public class ManagedConnection implement
 
     @Override
     public Object invoke(final Object proxy, final Method method, final 
Object[] args) throws Throwable {
-        final TransactionManager transactionManager = 
OpenEJB.getTransactionManager();
-        final Transaction transaction = transactionManager.getTransaction();
-        if (transaction == null) { // shouldn't be possible
-            return method.invoke(delegate, args);
-        }
+        try {
+            final TransactionManager transactionManager = 
OpenEJB.getTransactionManager();
+            final Transaction transaction = 
transactionManager.getTransaction();
+
+            if (transaction == null) { // shouldn't be possible
+                return method.invoke(delegate, args);
+            }
+
+            if (currentTransaction != null) {
+                if (isUnderTransaction(currentTransaction.getStatus())) {
+                    if (currentTransaction != transaction) {
+                        throw new SQLException("Connection can not be used 
while enlisted in another transaction");
+                    }
+                    return invokeUnderTransaction(delegate, method, args);
+                } else {
+                    System.out.println("no tx close");
+                    close(delegate);
+                }
+            }
+
+            int status = transaction.getStatus();
+            if (isUnderTransaction(status)) {
+                final Connection connection = 
CONNECTION_BY_TX.get(transaction);
+                if (connection != null) { // shared one
+                    System.out.println("conn != null close");
+                    delegate.close(); // return to pool
+                    delegate = connection;
+                } else {
+                    CONNECTION_BY_TX.put(transaction, delegate);
+                    currentTransaction = transaction;
+                    try {
+                        transaction.enlistResource(xaResource);
+                    } catch (RollbackException ignored) {
+                        // no-op
+                    } catch (SystemException e) {
+                        throw new SQLException("Unable to enlist connection 
the transaction", e);
+                    }
+                }
+                transaction.registerSynchronization(new 
ClosingSynchronization(delegate));
+
+                delegate.setAutoCommit(false); // TODO: previous value?
+
+                return invokeUnderTransaction(delegate, method, args);
+            }
+
 
-        int status = transaction.getStatus();
-        if (status != Status.STATUS_ACTIVE && status != 
Status.STATUS_MARKED_ROLLBACK) {
             return method.invoke(delegate, args);
+        } catch (InvocationTargetException ite) {
+            throw ite.getTargetException();
         }
+    }
 
-        // TODO: manage it properly
-        previousAutoCommit = delegate.getAutoCommit();
-        delegate.setAutoCommit(false);
-
+    private static Object invokeUnderTransaction(final Connection delegate, 
final Method method, final Object[] args) throws Exception, 
IllegalAccessException {
         final String mtdName = method.getName();
-        if ("setAutoCommit".equals(mtdName)) {
-            throw new SQLException("TODO");
-        } else if ("commit".equals(mtdName)) {
-            throw new SQLException("TODO");
-        } else if ("rollback".equals(mtdName)) {
-            throw new SQLException("TODO");
-        } else if ("setReadOnly".equals(mtdName)) {
-            throw new SQLException("TODO");
+        if ("setAutoCommit".equals(mtdName)
+                || "commit".equals(mtdName)
+                || "rollback".equals(mtdName)
+                || "setSavepoint".equals(mtdName)
+                || "setReadOnly".equals(mtdName)) {
+            throw forbiddenCall(mtdName);
+        }
+        if ("close".equals(mtdName)) {
+            // will be done later
+            // we need to differ it in case of rollback
+            return null;
         }
+        return method.invoke(delegate, args);
+    }
 
-        // TODO: manage share connection
+    private static boolean isUnderTransaction(int status) {
+        return status == Status.STATUS_ACTIVE || status == 
Status.STATUS_MARKED_ROLLBACK;
+    }
 
-        transaction.registerSynchronization(new 
ClosingSynchronization(delegate));
+    private static SQLException forbiddenCall(final String mtdName) {
+        return new SQLException("can't call " + mtdName + " when the 
connection is JtaManaged");
+    }
 
-        return method.invoke(delegate, args);
+    private static void close(final Connection connection) {
+        try {
+            if (!connection.isClosed()) {
+                connection.close();
+            }
+        } catch (SQLException e) {
+            // no-op
+        }
     }
 
     private static class ClosingSynchronization implements Synchronization {
@@ -76,9 +138,11 @@ public class ManagedConnection implement
 
         @Override
         public void afterCompletion(int status) {
+            close(connection);
             try {
-                connection.close();
-            } catch (SQLException e) {
+                final Transaction tx = 
OpenEJB.getTransactionManager().getTransaction();
+                CONNECTION_BY_TX.remove(tx);
+            } catch (SystemException ignored) {
                 // no-op
             }
         }

Modified: 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedDataSource.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedDataSource.java?rev=1364638&r1=1364637&r2=1364638&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedDataSource.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/ManagedDataSource.java
 Mon Jul 23 14:01:37 2012
@@ -28,26 +28,7 @@ public class ManagedDataSource implement
 
     @Override
     public Connection getConnection() throws SQLException {
-        final Connection connection = delegate.getConnection();
-        final XAResource xaResource = new LocalXAResource(connection);
-        final TransactionManager transactionManager = 
OpenEJB.getTransactionManager();
-        final Transaction transaction;
-        try {
-            transaction = transactionManager.getTransaction();
-        } catch (SystemException e) {
-            return managed(connection);
-        }
-        if (transaction != null) {
-            try {
-                transaction.enlistResource(xaResource);
-            } catch (RollbackException e) {
-                e.printStackTrace();  //To change body of catch statement use 
File | Settings | File Templates.
-            } catch (SystemException e) {
-                e.printStackTrace();  //To change body of catch statement use 
File | Settings | File Templates.
-            }
-        }
-
-        return managed(connection);
+        return managed(delegate.getConnection());
     }
 
     @Override

Modified: 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/LocalXAResource.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/LocalXAResource.java?rev=1364638&r1=1364637&r2=1364638&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/LocalXAResource.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/main/java/org/apache/openejb/resource/jdbc/managed/local/LocalXAResource.java
 Mon Jul 23 14:01:37 2012
@@ -104,8 +104,12 @@ public class LocalXAResource implements 
 
     @Override
     public synchronized void rollback(final Xid xid) throws XAException {
-        if (xid == null) throw new NullPointerException("xid is null");
-        if (!this.currentXid.equals(xid)) throw new XAException("Invalid Xid: 
expected " + this.currentXid + ", but was " + xid);
+        if (xid == null) {
+            throw new NullPointerException("xid is null");
+        }
+        if (!this.currentXid.equals(xid)) {
+            throw new XAException("Invalid Xid: expected " + this.currentXid + 
", but was " + xid);
+        }
 
         try {
             connection.rollback();

Modified: 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ManagedDataSourceTest.java
URL: 
http://svn.apache.org/viewvc/openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ManagedDataSourceTest.java?rev=1364638&r1=1364637&r2=1364638&view=diff
==============================================================================
--- 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ManagedDataSourceTest.java
 (original)
+++ 
openejb/trunk/openejb/container/openejb-core/src/test/java/org/apache/openejb/resource/jdbc/ManagedDataSourceTest.java
 Mon Jul 23 14:01:37 2012
@@ -5,9 +5,10 @@ import org.apache.openejb.jee.SingletonB
 import org.apache.openejb.junit.ApplicationComposer;
 import org.apache.openejb.junit.Configuration;
 import org.apache.openejb.junit.Module;
+import org.apache.openejb.resource.jdbc.managed.ManagedConnection;
 import org.apache.openejb.resource.jdbc.pool.DbcpDataSourceCreator;
+import org.junit.After;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -16,17 +17,19 @@ import javax.ejb.EJB;
 import javax.ejb.LocalBean;
 import javax.ejb.Singleton;
 import javax.sql.DataSource;
+import java.lang.reflect.Field;
 import java.sql.Connection;
 import java.sql.DriverManager;
 import java.sql.ResultSet;
 import java.sql.SQLException;
 import java.sql.Statement;
+import java.util.Map;
 import java.util.Properties;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
-@Ignore("to implement")
 @RunWith(ApplicationComposer.class)
 public class ManagedDataSourceTest {
     private static final String URL = "jdbc:hsqldb:mem:managed";
@@ -63,7 +66,8 @@ public class ManagedDataSourceTest {
         return p;
     }
 
-    @Module public SingletonBean app() throws Exception {
+    @Module
+    public SingletonBean app() throws Exception {
         final SingletonBean bean = new SingletonBean(PersistManager.class);
         bean.setLocalBean(new Empty());
         return bean;
@@ -113,6 +117,14 @@ public class ManagedDataSourceTest {
         assertFalse(exists(2));
     }
 
+    @After
+    public void checkTxMapIsEmpty() throws Exception {
+        final Field map = 
ManagedConnection.class.getDeclaredField("CONNECTION_BY_TX");
+        map.setAccessible(true);
+        final Map<?, ?> instance = (Map<?, ?>) map.get(null);
+        assertEquals(0, instance.size());
+    }
+
     private static boolean exists(int id) throws SQLException {
         final Connection connection = DriverManager.getConnection(URL, USER, 
PASSWORD);
         final Statement statement = connection.createStatement();


Reply via email to