You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2009/10/11 03:52:35 UTC

svn commit: r823997 - in /openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta: ./ ContainerTest.java JTAManagedRuntime.java SimpleTransaction.java SimpleTransactionManager.java

Author: ppoddar
Date: Sun Oct 11 01:52:34 2009
New Revision: 823997

URL: http://svn.apache.org/viewvc?rev=823997&view=rev
Log:
OPENJOA-1342: Support simple/basic container test harness for managed transaction

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/ContainerTest.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/JTAManagedRuntime.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransaction.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransactionManager.java   (with props)

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/ContainerTest.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/ContainerTest.java?rev=823997&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/ContainerTest.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/ContainerTest.java Sun Oct 11 01:52:34 2009
@@ -0,0 +1,90 @@
+/*
+ * 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.openjpa.jta;
+
+import javax.transaction.TransactionManager;
+
+import org.apache.openjpa.ee.ManagedRuntime;
+import org.apache.openjpa.persistence.test.SingleEMFTestCase;
+
+/**
+ * Simulates a container transaction around a test method.
+ * 
+ * The concrete tests derived from this class must adhere to the following guidelines:
+ * <LI>They must configure openjpa.ManagedRuntime in setUp() properties as
+ * to <code>org.apache.openjpa.jta.JTAManagedRuntime</code> 
+ * 
+ * <LI>The tests themselves must not try to access the transaction directly 
+ * i.e. not call EntityManager.getTransaction(). Attempt to do so will raise
+ * exception.
+ * 
+ * <LI>The test methods must use  EntityManager.joinTransaction() to use a transaction.
+ * This test harness ensures that a transaction is active before running each
+ * test method.
+ * 
+ * <LI>The test methods may call commit() and rollback() methods of this class
+ * to demarcate transaction.  
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public abstract class ContainerTest extends SingleEMFTestCase {
+    ManagedRuntime runtime;
+    
+    @Override
+    public void setUp(Object...props) {
+        super.setUp(props);
+        runtime = emf.getConfiguration().getManagedRuntimeInstance();
+        assertNotNull(runtime);
+    }
+    
+    @Override
+    public void runTest() throws Throwable {
+        TransactionManager txm = runtime.getTransactionManager();
+        txm.begin();
+        try {
+            super.runTest();
+        } catch (Throwable t) {
+            t.printStackTrace();
+            throw t;
+        }
+    }
+    
+    @Override
+    public void tearDown() throws Exception {
+    }
+    
+    protected void commit() {
+        try {
+            runtime.getTransactionManager().commit();
+        } catch (Throwable e) {
+            e.printStackTrace();
+        } 
+    }
+    
+    protected void rollback() {
+        try {
+            runtime.getTransactionManager().rollback();
+        } catch (Throwable e) {
+            e.printStackTrace();
+        } 
+    }
+    
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/ContainerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/JTAManagedRuntime.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/JTAManagedRuntime.java?rev=823997&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/JTAManagedRuntime.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/JTAManagedRuntime.java Sun Oct 11 01:52:34 2009
@@ -0,0 +1,57 @@
+/*
+ * 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.openjpa.jta;
+
+import javax.transaction.NotSupportedException;
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+
+import org.apache.openjpa.ee.ManagedRuntime;
+/**
+ * An implementation of {@linkplain ManagedRuntime managed runtime} for testing
+ * JTA resources in a JSE environment without a <em>real</em> and often heavy
+ * container. Uses a {@linkplain simple} (or basic) TransactionManager.
+ *  
+ * @author Pinaki Poddar
+ *
+ */
+public class JTAManagedRuntime implements ManagedRuntime {
+    private SimpleTransactionManager txm = new SimpleTransactionManager();
+    
+    public void doNonTransactionalWork(Runnable runnable) throws NotSupportedException {
+        throw new NotSupportedException();
+    }
+
+    public Throwable getRollbackCause() throws Exception {
+        return txm.getTransaction().getRollbackCause();
+    }
+
+    public Object getTransactionKey() throws Exception, SystemException {
+        return getTransactionManager().getTransaction().hashCode();
+    }
+
+    public TransactionManager getTransactionManager() throws Exception {
+        return txm;
+    }
+
+    public void setRollbackOnly(Throwable cause) throws Exception {
+        txm.getTransaction().setRollbackOnly(cause);
+    }
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/JTAManagedRuntime.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransaction.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransaction.java?rev=823997&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransaction.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransaction.java Sun Oct 11 01:52:34 2009
@@ -0,0 +1,175 @@
+/*
+ * 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.openjpa.jta;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.xa.XAResource;
+
+/**
+ * A transaction for testing.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class SimpleTransaction implements Transaction {
+    private final Set<Synchronization> synchs = new HashSet<Synchronization>();
+    private Throwable rollbackCause;
+    private volatile int status = Status.STATUS_UNKNOWN;
+    
+    /**
+     * Commits this transaction.
+     */
+    public void commit() throws HeuristicMixedException, HeuristicRollbackException, RollbackException,
+            SecurityException, SystemException {
+        if (status == Status.STATUS_MARKED_ROLLBACK)
+            throw new RuntimeException(this + " can not commit. Marked for rollback");
+        status = Status.STATUS_COMMITTING;
+        List<Throwable> errors = new ArrayList<Throwable>();
+        for (Synchronization synch : synchs) {
+            try {
+                synch.beforeCompletion();
+            } catch (Throwable t) {
+                errors.add(t);
+            }
+        }
+        // do nothing
+        for (Synchronization synch : synchs) {
+            try {
+                synch.afterCompletion(Status.STATUS_COMMITTED);
+            } catch (Throwable t) {
+                errors.add(t);
+            }
+        }
+        status = errors.isEmpty() ? Status.STATUS_COMMITTED : Status.STATUS_UNKNOWN;
+    }
+
+    /**
+     * Not implemented.
+     * Raises UnsupportedOperationException.
+     */
+    public boolean delistResource(XAResource arg0, int arg1) throws IllegalStateException, SystemException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not implemented.
+     * Raises UnsupportedOperationException.
+     */
+    public boolean enlistResource(XAResource arg0) throws IllegalStateException, RollbackException, SystemException {
+        return false;
+    }
+
+    /**
+     * Gets the status of this transaction.
+     * Raises UnsupportedOperationException.
+     */
+    public int getStatus() throws SystemException {
+        return status;
+    }
+    
+    void setStatus(int newStatus) throws SystemException {
+        status = newStatus;
+    }
+    
+
+    /**
+     * Registers the given synchronization element.
+     */
+    public void registerSynchronization(Synchronization synch) throws IllegalStateException, RollbackException,
+            SystemException {
+        synchs.add(synch);
+    }
+
+    /**
+     * Rolls back this transaction.
+     */
+    public void rollback() throws IllegalStateException, SystemException {
+        status = Status.STATUS_ROLLING_BACK;
+        List<Throwable> errors = new ArrayList<Throwable>();
+        for (Synchronization synch : synchs) {
+            try {
+                synch.beforeCompletion();
+            } catch (Throwable t) {
+                errors.add(t);
+            }
+        }
+        
+        for (Synchronization synch : synchs) {
+            try {
+                synch.afterCompletion(Status.STATUS_ROLLEDBACK);
+            } catch (Throwable t) {
+                errors.add(t);
+            }
+        }
+        status = errors.isEmpty() ? Status.STATUS_ROLLEDBACK : Status.STATUS_UNKNOWN;
+        if (!errors.isEmpty()) 
+            throw new RuntimeException(errors.get(0));
+    }
+
+    /**
+     * Marks this transaction for rollback only.
+     */
+    public void setRollbackOnly() throws IllegalStateException, SystemException {
+        setRollbackOnly(null);
+    }
+    
+    /**
+     * Marks this transaction for rollback only with the given underlying cause.
+     */
+    void setRollbackOnly(Throwable cause) throws IllegalStateException, SystemException {
+        rollbackCause = cause;
+        status = Status.STATUS_MARKED_ROLLBACK;
+    }
+    
+    Throwable getRollbackCause() {
+        return rollbackCause;
+    }
+    
+    public String toString() {
+        return "TXN:"+hashCode() +"["+statusCode()+"]";
+    }
+    
+    String statusCode() {
+        switch (status) {
+        case Status.STATUS_ACTIVE          : return "active";
+        case Status.STATUS_COMMITTED       : return "committed";
+        case Status.STATUS_COMMITTING      : return "committing";
+        case Status.STATUS_MARKED_ROLLBACK : return "marked rollback";
+        case Status.STATUS_NO_TRANSACTION  : return "none";
+        case Status.STATUS_PREPARED        : return "prepared";
+        case Status.STATUS_PREPARING       : return "preparing";
+        case Status.STATUS_ROLLEDBACK      : return "rolled back";
+        case Status.STATUS_ROLLING_BACK    : return "rolling back";
+        case Status.STATUS_UNKNOWN         : return "unknown";
+        default                            : return "error";
+        }
+    }
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransaction.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransactionManager.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransactionManager.java?rev=823997&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransactionManager.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransactionManager.java Sun Oct 11 01:52:34 2009
@@ -0,0 +1,154 @@
+/*
+ * 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.openjpa.jta;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+/**
+ * A very very simple Transaction Manager for testing JTA resource 
+ * without a container.
+ * <br>
+ * Provides a single transaction per-thread model.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class SimpleTransactionManager implements TransactionManager {
+    private static ThreadLocal<SimpleTransaction> txns = new ThreadLocal<SimpleTransaction>();
+    
+    /**
+     * Begins a new transaction associated with the current thread.
+     * 
+     */
+    public void begin() throws NotSupportedException, SystemException {
+        SimpleTransaction txn = getTransaction();
+        int status = txn.getStatus();
+        if (status == Status.STATUS_COMMITTED || status == Status.STATUS_ROLLEDBACK || status == Status.STATUS_UNKNOWN
+         || status == Status.STATUS_ACTIVE)
+            txn.setStatus(Status.STATUS_ACTIVE);
+        else
+            throw new IllegalStateException("Can not begin " + txn);
+    }
+
+    /**
+     * Commits a transaction associated with the current thread.
+     * Raises IllegalStateException if no transaction is associated with the current thread. 
+     * 
+     */
+    public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException,
+            RollbackException, SecurityException, SystemException {
+        assertActiveTransaction();
+        try {
+            getTransaction().commit();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            txns.set(null);
+        }
+        
+    }
+
+    /**
+     * Gets the status of the transaction associated with the current thread.
+     */
+    public int getStatus() throws SystemException {
+        if (txns.get() == null)
+            return Status.STATUS_NO_TRANSACTION;
+        return getTransaction().getStatus();
+    }
+
+    /**
+     * Gets the transaction associated with the current thread.
+     * If no transaction is associated then creates a transaction and
+     * associates with the current thread.
+     */
+    public SimpleTransaction getTransaction() throws SystemException {
+        SimpleTransaction txn = txns.get();
+        if (txn == null) {
+            txn = new SimpleTransaction();
+            txn.setStatus(Status.STATUS_ACTIVE);
+            txns.set(txn);
+        }
+        return txn;
+    }
+
+    /**
+     * Not implemented. 
+     * Raises UnsupportedOperationException.
+     */
+    public void resume(Transaction arg0) throws IllegalStateException, InvalidTransactionException, SystemException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Rolls back a transaction associated with the current thread.
+     * Raises IllegalStateException if no transaction is associated with the current thread. 
+     * 
+     */
+    public void rollback() throws IllegalStateException, SecurityException, SystemException {
+        assertActiveTransaction();
+        try {
+            getTransaction().rollback();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            txns.set(null);
+        }
+    }
+
+    /**
+     * Marks a transaction associated with the current thread for rollback.
+     * Raises IllegalStateException if no transaction is associated with the current thread. 
+     * 
+     */
+    public void setRollbackOnly() throws IllegalStateException, SystemException {
+        assertActiveTransaction();
+        getTransaction().setRollbackOnly();
+    }
+
+    /**
+     * Not implemented. 
+     * Raises UnsupportedOperationException.
+     */
+    public void setTransactionTimeout(int arg0) throws SystemException {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Not implemented. 
+     * Raises UnsupportedOperationException.
+     */
+    public Transaction suspend() throws SystemException {
+        throw new UnsupportedOperationException();
+    }
+    
+    void assertActiveTransaction() throws IllegalStateException, SystemException {
+        if (getStatus() == Status.STATUS_NO_TRANSACTION)
+            throw new IllegalStateException("No transaction on " + Thread.currentThread());
+    }
+
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/jta/SimpleTransactionManager.java
------------------------------------------------------------------------------
    svn:eol-style = native