mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-10-08 14:51:49 +00:00
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:
@@ -208,12 +208,6 @@ public class RetryingTransactionHelper
|
||||
*/
|
||||
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
|
||||
* @author Derek Hulley
|
||||
@@ -464,11 +458,7 @@ public class RetryingTransactionHelper
|
||||
// Only commit if we 'own' the transaction.
|
||||
if (txn != null)
|
||||
{
|
||||
// Check if force rollback is on
|
||||
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 (txn.getStatus() == Status.STATUS_MARKED_ROLLBACK)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
{
|
||||
@@ -521,10 +511,6 @@ public class RetryingTransactionHelper
|
||||
" Exception follows:",
|
||||
e);
|
||||
}
|
||||
|
||||
// make sure we don't leak the state
|
||||
rollbackOnly.set(null);
|
||||
|
||||
// Rollback if we can.
|
||||
if (txn != null)
|
||||
{
|
||||
@@ -684,29 +670,6 @@ public class RetryingTransactionHelper
|
||||
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
|
||||
* marked for rollback.
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2011 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -80,13 +80,11 @@ public class RetryingTransactionInterceptor extends TransactionAspectSupport imp
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
RetryingTransactionHelper.setRollbackOnly();
|
||||
completeTransactionAfterThrowing(txInfo, e);
|
||||
throw e;
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
RetryingTransactionHelper.setRollbackOnly();
|
||||
// Wrap non-runtime exceptions so that they can be preserved
|
||||
completeTransactionAfterThrowing(txInfo, e);
|
||||
throw new WrapperException(e);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (C) 2005-2015 Alfresco Software Limited.
|
||||
* Copyright (C) 2005-2012 Alfresco Software Limited.
|
||||
*
|
||||
* This file is part of Alfresco
|
||||
*
|
||||
@@ -703,61 +703,6 @@ public class NodeServiceTest
|
||||
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)
|
||||
{
|
||||
RetryingTransactionCallback<NodeRef> setupCallback = new RetryingTransactionCallback<NodeRef>()
|
||||
|
Reference in New Issue
Block a user