Merged HEAD-BUG-FIX (5.1/Cloud) to HEAD (5.1/Cloud)

99771: Merged 5.0.N (5.0.2) to HEAD-BUG-FIX (5.1/Cloud)
      99702: Merged V4.2-BUG-FIX (4.2.5) to 5.0.N (5.0.2)
         99655: Reverse Merge V4.2-BUG-FIX (4.2.5)
            << Caused build failures >>
            99553: MNT-12628: Following on from MNT-12501 - Rollback of synchronous transactions is not behaving consistently
               - Added a static variable holding the RollbackOnly state to RetryingTransactionHelper. Currently used by RetryingTransactionInterceptor.


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@100498 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
Alan Davis
2015-03-27 22:57:20 +00:00
parent ea2418e9be
commit bc6720c6cc
3 changed files with 3 additions and 97 deletions

View File

@@ -208,12 +208,6 @@ public class RetryingTransactionHelper
*/ */
private List<Class<?>> extraExceptions; private List<Class<?>> extraExceptions;
/**
* A local variable holding the Rollback-only transaction flag which can be set by {@link #setRollbackOnly()}
* and is flushed by the
*/
private static ThreadLocal<Boolean> rollbackOnly = new ThreadLocal<Boolean>();
/** /**
* Callback interface * Callback interface
* @author Derek Hulley * @author Derek Hulley
@@ -464,11 +458,7 @@ public class RetryingTransactionHelper
// Only commit if we 'own' the transaction. // Only commit if we 'own' the transaction.
if (txn != null) if (txn != null)
{ {
// Check if force rollback is on if (txn.getStatus() == Status.STATUS_MARKED_ROLLBACK)
boolean mustRollBack = isRollbackOnly();
// This method owns the transaction; make sure we don't leak the state
rollbackOnly.set(null);
if (txn.getStatus() == Status.STATUS_MARKED_ROLLBACK || mustRollBack)
{ {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
{ {
@@ -521,10 +511,6 @@ public class RetryingTransactionHelper
" Exception follows:", " Exception follows:",
e); e);
} }
// make sure we don't leak the state
rollbackOnly.set(null);
// Rollback if we can. // Rollback if we can.
if (txn != null) if (txn != null)
{ {
@@ -684,29 +670,6 @@ public class RetryingTransactionHelper
return retryCause; return retryCause;
} }
/**
* @return Returns <tt>true</tt> if the current thread transaction was marked as RollbackOnly
*/
public static boolean isRollbackOnly()
{
if (rollbackOnly.get() == null)
{
return false;
}
else
{
return rollbackOnly.get();
}
}
/**
* Helper method to set the RollbackOnly state of the transaction in the current thread
*/
public static void setRollbackOnly()
{
rollbackOnly.set(true);
}
/** /**
* Utility method to get the active transaction. The transaction status can be queried and * Utility method to get the active transaction. The transaction status can be queried and
* marked for rollback. * marked for rollback.

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2015 Alfresco Software Limited. * Copyright (C) 2005-2011 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -80,13 +80,11 @@ public class RetryingTransactionInterceptor extends TransactionAspectSupport imp
} }
catch (RuntimeException e) catch (RuntimeException e)
{ {
RetryingTransactionHelper.setRollbackOnly();
completeTransactionAfterThrowing(txInfo, e); completeTransactionAfterThrowing(txInfo, e);
throw e; throw e;
} }
catch (Throwable e) catch (Throwable e)
{ {
RetryingTransactionHelper.setRollbackOnly();
// Wrap non-runtime exceptions so that they can be preserved // Wrap non-runtime exceptions so that they can be preserved
completeTransactionAfterThrowing(txInfo, e); completeTransactionAfterThrowing(txInfo, e);
throw new WrapperException(e); throw new WrapperException(e);

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2005-2015 Alfresco Software Limited. * Copyright (C) 2005-2012 Alfresco Software Limited.
* *
* This file is part of Alfresco * This file is part of Alfresco
* *
@@ -703,61 +703,6 @@ public class NodeServiceTest
assertEquals("Expected exact number of reference assocs", 1, childAssocRefs.size()); assertEquals("Expected exact number of reference assocs", 1, childAssocRefs.size());
} }
/**
* Test for MNT-12501
*/
@Test public void testRollbackTransaction()
{
final NodeRef workspaceRootNodeRef = nodeService.getRootNode(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE);
final String name = GUID.generate();
final NodeRef[] nodes = new NodeRef[2];
// Now create 2 nodes with the same name and swallow the exception inside
RetryingTransactionCallback<Void> newNodeCallback = new RetryingTransactionCallback<Void>()
{
@Override
public Void execute() throws Throwable
{
Map<QName, Serializable> props = new HashMap<QName, Serializable>(3);
props.put(ContentModel.PROP_NAME, name);
try
{
NodeRef node1 = nodeService.createNode(
workspaceRootNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NAMESPACE, "duplicate"),
ContentModel.TYPE_FOLDER,
props).getChildRef();
nodes[0] = node1;
NodeRef node2 = nodeService.createNode(
workspaceRootNodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName(NAMESPACE, "duplicate"),
ContentModel.TYPE_FOLDER,
props).getChildRef();
nodes[1] = node2;
}
catch (Exception e)
{
// swallow the exception
}
return null;
}
};
try
{
txnService.getRetryingTransactionHelper().doInTransaction(newNodeCallback);
// The exception is swallowed inside the callback
//fail("Duplicate child node name not detected.");
}
catch (DuplicateChildNodeNameException e)
{
// The exception is swallowed inside the callback
}
assertNotNull("The first node was not created.", nodes[0]);
assertFalse("The node creation should be rolled back.", nodeService.exists(nodes[0]));
assertNull("The duplicate node should not be created.", nodes[1]);
}
private NodeRef setupTestGetChildren(final NodeRef workspaceRootNodeRef, final int numberOfReferences) private NodeRef setupTestGetChildren(final NodeRef workspaceRootNodeRef, final int numberOfReferences)
{ {
RetryingTransactionCallback<NodeRef> setupCallback = new RetryingTransactionCallback<NodeRef>() RetryingTransactionCallback<NodeRef> setupCallback = new RetryingTransactionCallback<NodeRef>()