diff --git a/src/main/java/org/alfresco/util/transaction/TransactionSupportUtil.java b/src/main/java/org/alfresco/util/transaction/TransactionSupportUtil.java index fc4c4e2429..05f7bac5a1 100644 --- a/src/main/java/org/alfresco/util/transaction/TransactionSupportUtil.java +++ b/src/main/java/org/alfresco/util/transaction/TransactionSupportUtil.java @@ -480,7 +480,7 @@ public abstract class TransactionSupportUtil // These are still considered part of the transaction so are executed here doBeforeCommit(readOnly); - // Now run the > 0 listeners beforeCommit + // Now run the != 0 listeners beforeCommit Set priorities = priorityLookup.keySet(); SortedSet sortedPriorities = new ConcurrentSkipListSet(FORWARD_INTEGER_ORDER); @@ -526,8 +526,7 @@ public abstract class TransactionSupportUtil */ private void doBeforeCommit(Set visitedListeners, boolean readOnly) { - Set listeners = priorityLookup.get(0); - Set pendingListeners = new HashSet(listeners); + List pendingListeners = getLevelZeroListenersIterable(); pendingListeners.removeAll(visitedListeners); if (pendingListeners.size() != 0) diff --git a/src/test/java/org/alfresco/util/transaction/SpringAwareUserTransactionTest.java b/src/test/java/org/alfresco/util/transaction/SpringAwareUserTransactionTest.java index 5c218bbafe..2b11281c5d 100644 --- a/src/test/java/org/alfresco/util/transaction/SpringAwareUserTransactionTest.java +++ b/src/test/java/org/alfresco/util/transaction/SpringAwareUserTransactionTest.java @@ -19,6 +19,7 @@ package org.alfresco.util.transaction; import java.util.NoSuchElementException; +import java.util.Objects; import javax.transaction.RollbackException; import javax.transaction.Status; @@ -321,6 +322,86 @@ public class SpringAwareUserTransactionTest extends TestCase TransactionDefinition.TIMEOUT_DEFAULT); } + public void testTransactionListenerOrder() throws Throwable + { + testNoTxnStatus(); + try + { + txn.begin(); + StringBuffer buffer = new StringBuffer(); + TransactionSupportUtil.bindListener(new TestTransactionListener("5x", buffer), 5); + TransactionSupportUtil.bindListener(new TestTransactionListener("0a", buffer), 0); + TransactionSupportUtil.bindListener(new TestTransactionListener("0e", buffer), 0); + TransactionSupportUtil.bindListener(new TestTransactionListener("0d", buffer), 0); + TransactionSupportUtil.bindListener(new TestTransactionListener("0b", buffer), 0); + TransactionSupportUtil.bindListener(new TestTransactionListener("0c", buffer), 0); + TransactionSupportUtil.bindListener(new TestTransactionListener("4x", buffer), 4); + TransactionSupportUtil.bindListener(new TestTransactionListener("1x", buffer), -1); + TransactionSupportUtil.bindListener(new TestTransactionListener("3a", buffer), 3); + TransactionSupportUtil.bindListener(new TestTransactionListener("3e", buffer), 3); + TransactionSupportUtil.bindListener(new TestTransactionListener("3d", buffer), 3); + TransactionSupportUtil.bindListener(new TestTransactionListener("3b", buffer), 3); + TransactionSupportUtil.bindListener(new TestTransactionListener("3c", buffer), 3); + TransactionSupportUtil.bindListener(new TestTransactionListener("2x", buffer), -2); + txn.commit(); + assertEquals("0a0e0d0b0c2x1x3a3e3d3b3c4x5x", buffer.toString()); + } + catch (Exception e) + { + try + { + txn.rollback(); + } + catch (Exception ee) + { + e.addSuppressed(ee); + } + throw e; + } + checkNoStatusOnThread(); + } + + private static class TestTransactionListener extends TransactionListenerAdapter + { + private final String name; + private final StringBuffer buffer; + + public TestTransactionListener(String name, StringBuffer buffer) + { + Objects.requireNonNull(name); + Objects.requireNonNull(buffer); + this.name = name; + this.buffer = buffer; + } + + @Override + public void beforeCommit(boolean readOnly) + { + buffer.append(name); + } + + public String getName() + { + return name; + } + + @Override + public boolean equals(Object obj) + { + if (obj instanceof TestTransactionListener) + { + return name.equals(((TestTransactionListener) obj).getName()); + } + return false; + } + + @Override + public int hashCode() + { + return name.hashCode(); + } + } + /** * Used to check that the transaction manager is being called correctly *