mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
Merged V3.0 to HEAD
11535: Fix ETHREEOH-519, ETHREEOH-23, ETHREEOH-24, ETHREEOH-58, ETHREEOH-449, ETHREEOH-30, ETHREEOH-19, ETHREEOH-561, ETHREEOH-537, ETHREEOH-567, ETHREEOH-568, ETHREEOH-113, ETHREEOH-130, ETHREEOH-115, ETHREEOH-566, ETHREEOH-572, ETHREEOH-82. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@12450 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.transaction;
|
package org.alfresco.repo.transaction;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.sql.BatchUpdateException;
|
import java.sql.BatchUpdateException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
@@ -44,8 +45,11 @@ import org.apache.commons.logging.LogFactory;
|
|||||||
import org.hibernate.ObjectNotFoundException;
|
import org.hibernate.ObjectNotFoundException;
|
||||||
import org.hibernate.StaleObjectStateException;
|
import org.hibernate.StaleObjectStateException;
|
||||||
import org.hibernate.StaleStateException;
|
import org.hibernate.StaleStateException;
|
||||||
|
import org.hibernate.cache.CacheException;
|
||||||
import org.hibernate.exception.ConstraintViolationException;
|
import org.hibernate.exception.ConstraintViolationException;
|
||||||
import org.hibernate.exception.LockAcquisitionException;
|
import org.hibernate.exception.LockAcquisitionException;
|
||||||
|
import org.springframework.aop.MethodBeforeAdvice;
|
||||||
|
import org.springframework.aop.framework.ProxyFactory;
|
||||||
import org.springframework.dao.ConcurrencyFailureException;
|
import org.springframework.dao.ConcurrencyFailureException;
|
||||||
import org.springframework.dao.DataIntegrityViolationException;
|
import org.springframework.dao.DataIntegrityViolationException;
|
||||||
import org.springframework.dao.DeadlockLoserDataAccessException;
|
import org.springframework.dao.DeadlockLoserDataAccessException;
|
||||||
@@ -74,6 +78,7 @@ import org.springframework.jdbc.UncategorizedSQLException;
|
|||||||
public class RetryingTransactionHelper
|
public class RetryingTransactionHelper
|
||||||
{
|
{
|
||||||
private static final String MSG_READ_ONLY = "permissions.err_read_only";
|
private static final String MSG_READ_ONLY = "permissions.err_read_only";
|
||||||
|
private static final String KEY_ACTIVE_TRANSACTION = "RetryingTransactionHelper.ActiveTxn";
|
||||||
private static Log logger = LogFactory.getLog(RetryingTransactionHelper.class);
|
private static Log logger = LogFactory.getLog(RetryingTransactionHelper.class);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,7 +100,8 @@ public class RetryingTransactionHelper
|
|||||||
DataIntegrityViolationException.class,
|
DataIntegrityViolationException.class,
|
||||||
StaleStateException.class,
|
StaleStateException.class,
|
||||||
ObjectNotFoundException.class,
|
ObjectNotFoundException.class,
|
||||||
RemoteCacheException.class
|
CacheException.class, // Usually a cache replication issue
|
||||||
|
RemoteCacheException.class // A cache replication issue
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -104,6 +110,8 @@ public class RetryingTransactionHelper
|
|||||||
*/
|
*/
|
||||||
private TransactionService txnService;
|
private TransactionService txnService;
|
||||||
|
|
||||||
|
// /** Performs post-failure exception neatening */
|
||||||
|
// private ExceptionTransformer exceptionTransformer;
|
||||||
/** The maximum number of retries. -1 for infinity. */
|
/** The maximum number of retries. -1 for infinity. */
|
||||||
private int maxRetries;
|
private int maxRetries;
|
||||||
/** The minimum time to wait between retries. */
|
/** The minimum time to wait between retries. */
|
||||||
@@ -151,6 +159,16 @@ public class RetryingTransactionHelper
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Setters.
|
// Setters.
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * Optionally set the component that will transform or neaten any exceptions that are
|
||||||
|
// * propagated.
|
||||||
|
// */
|
||||||
|
// public void setExceptionTransformer(ExceptionTransformer exceptionTransformer)
|
||||||
|
// {
|
||||||
|
// this.exceptionTransformer = exceptionTransformer;
|
||||||
|
// }
|
||||||
|
//
|
||||||
/**
|
/**
|
||||||
* Set the TransactionService.
|
* Set the TransactionService.
|
||||||
*/
|
*/
|
||||||
@@ -289,6 +307,14 @@ public class RetryingTransactionHelper
|
|||||||
if (txn != null)
|
if (txn != null)
|
||||||
{
|
{
|
||||||
txn.begin();
|
txn.begin();
|
||||||
|
// Wrap it to protect it
|
||||||
|
UserTransactionProtectionAdvise advise = new UserTransactionProtectionAdvise();
|
||||||
|
ProxyFactory proxyFactory = new ProxyFactory(txn);
|
||||||
|
proxyFactory.addAdvice(advise);
|
||||||
|
UserTransaction wrappedTxn = (UserTransaction) proxyFactory.getProxy();
|
||||||
|
// Store the UserTransaction for static retrieval. There is no need to unbind it
|
||||||
|
// because the transaction management will do that for us.
|
||||||
|
AlfrescoTransactionSupport.bindResource(KEY_ACTIVE_TRANSACTION, wrappedTxn);
|
||||||
}
|
}
|
||||||
// Do the work.
|
// Do the work.
|
||||||
R result = cb.execute();
|
R result = cb.execute();
|
||||||
@@ -340,12 +366,12 @@ public class RetryingTransactionHelper
|
|||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
{
|
{
|
||||||
logger.debug("\n" +
|
logger.debug("\n" +
|
||||||
"Transaction commit failed: \n" +
|
"Transaction commit failed: \n" +
|
||||||
" Thread: " + Thread.currentThread().getName() + "\n" +
|
" Thread: " + Thread.currentThread().getName() + "\n" +
|
||||||
" Txn: " + txn + "\n" +
|
" Txn: " + txn + "\n" +
|
||||||
" Iteration: " + count + "\n" +
|
" Iteration: " + count + "\n" +
|
||||||
" Exception follows:",
|
" Exception follows:",
|
||||||
e);
|
e);
|
||||||
}
|
}
|
||||||
// Rollback if we can.
|
// Rollback if we can.
|
||||||
if (txn != null)
|
if (txn != null)
|
||||||
@@ -440,4 +466,44 @@ public class RetryingTransactionHelper
|
|||||||
return retryCause;
|
return retryCause;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method to get the active transaction. The transaction status can be queried and
|
||||||
|
* marked for rollback.
|
||||||
|
* <p>
|
||||||
|
* <b>NOTE:</b> Any attempt to actually commit or rollback the transaction will cause failures.
|
||||||
|
*
|
||||||
|
* @return Returns the currently active user transaction or <tt>null</tt> if
|
||||||
|
* there isn't one.
|
||||||
|
*/
|
||||||
|
public static UserTransaction getActiveUserTransaction()
|
||||||
|
{
|
||||||
|
// Dodge if there is no wrapping transaction
|
||||||
|
if (AlfrescoTransactionSupport.getTransactionReadState() == TxnReadState.TXN_NONE)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Get the current transaction. There might not be one if the transaction was not started using
|
||||||
|
// this class i.e. it wasn't started with retries.
|
||||||
|
UserTransaction txn = (UserTransaction) AlfrescoTransactionSupport.getResource(KEY_ACTIVE_TRANSACTION);
|
||||||
|
if (txn == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
return txn;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class UserTransactionProtectionAdvise implements MethodBeforeAdvice
|
||||||
|
{
|
||||||
|
public void before(Method method, Object[] args, Object target) throws Throwable
|
||||||
|
{
|
||||||
|
String methodName = method.getName();
|
||||||
|
if (methodName.equals("begin") || methodName.equals("commit") || methodName.equals("rollback"))
|
||||||
|
{
|
||||||
|
throw new IllegalAccessException(
|
||||||
|
"The user transaction cannot be manipulated from within the transactional work load");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user