TransactionSynchronization
instances
* are registered on behalf of the application code.
*
+ * This class remains for backward API compatibility,
+ * @deprecated use the Core Project TransactionSupportUtil instead
+ *
* @author Derek Hulley
*/
-public abstract class AlfrescoTransactionSupport
+public abstract class AlfrescoTransactionSupport extends TransactionSupportUtil
{
/*
* The registrations of services is very explicit on the interface. This
@@ -56,6 +62,12 @@ public abstract class AlfrescoTransactionSupport
* list of types of services that need registration, this is still
* OK.
*/
+
+ private static int COMMIT_ORDER_NORMAL=0;
+ private static int COMMIT_ORDER_INTEGRITY=1;
+ private static int COMMIT_ORDER_LUCENE=2;
+ private static int COMMIT_ORDER_DAO=3;
+ private static int COMMIT_ORDER_CACHE=4;
/**
* The order of synchronization set to be 100 less than the Hibernate synchronization order
@@ -63,74 +75,9 @@ public abstract class AlfrescoTransactionSupport
public static final int SESSION_SYNCHRONIZATION_ORDER =
SessionFactoryUtils.SESSION_SYNCHRONIZATION_ORDER - 100;
- /** resource key to store the transaction synchronizer instance */
- private static final String RESOURCE_KEY_TXN_SYNCH = "txnSynch";
- /** resource binding during after-completion phase */
- private static final String RESOURCE_KEY_TXN_COMPLETING = "AlfrescoTransactionSupport.txnCompleting";
private static Log logger = LogFactory.getLog(AlfrescoTransactionSupport.class);
- /**
- * @return Returns the system time when the transaction started, or -1 if there is no current transaction.
- */
- public static long getTransactionStartTime()
- {
- /*
- * This method can be called outside of a transaction, so we can go direct to the synchronizations.
- */
- TransactionSynchronizationImpl txnSynch =
- (TransactionSynchronizationImpl) TransactionSynchronizationManager.getResource(RESOURCE_KEY_TXN_SYNCH);
- if (txnSynch == null)
- {
- if (TransactionSynchronizationManager.isSynchronizationActive())
- {
- // need to lazily register synchronizations
- return registerSynchronizations().getTransactionStartTime();
- }
- else
- {
- return -1; // not in a transaction
- }
- }
- else
- {
- return txnSynch.getTransactionStartTime();
- }
- }
-
- /**
- * Get a unique identifier associated with each transaction of each thread. Null is returned if
- * no transaction is currently active.
- *
- * @return Returns the transaction ID, or null if no transaction is present
- */
- public static String getTransactionId()
- {
- /*
- * Go direct to the synchronizations as we don't want to register a resource if one doesn't exist.
- * This method is heavily used, so the simple Map lookup on the ThreadLocal is the fastest.
- */
-
- TransactionSynchronizationImpl txnSynch =
- (TransactionSynchronizationImpl) TransactionSynchronizationManager.getResource(RESOURCE_KEY_TXN_SYNCH);
- if (txnSynch == null)
- {
- if (TransactionSynchronizationManager.isSynchronizationActive())
- {
- // need to lazily register synchronizations
- return registerSynchronizations().getTransactionId();
- }
- else
- {
- return null; // not in a transaction
- }
- }
- else
- {
- return txnSynch.getTransactionId();
- }
- }
-
/**
*
* @author Derek Hulley
@@ -146,10 +93,7 @@ public abstract class AlfrescoTransactionSupport
TXN_READ_WRITE
}
- public static boolean isActualTransactionActive()
- {
- return TransactionSynchronizationManager.isActualTransactionActive();
- }
+
/**
* @return Returns the read-write state of the current transaction
@@ -162,7 +106,7 @@ public abstract class AlfrescoTransactionSupport
return TxnReadState.TXN_NONE;
}
// Find the read-write state of the txn
- if (AlfrescoTransactionSupport.getResource(RESOURCE_KEY_TXN_COMPLETING) != null)
+ if (getResource(RESOURCE_KEY_TXN_COMPLETING) != null)
{
// Transaction is completing. For all intents and purposes, we are not in a transaction.
return TxnReadState.TXN_NONE;
@@ -212,93 +156,35 @@ public abstract class AlfrescoTransactionSupport
*
* @deprecated To be replaced by {@link DirtySessionMethodInterceptor}
*/
- public static boolean isDirty()
+ public static boolean isDirty()
{
- TransactionSynchronizationImpl synch = getSynchronization();
-
- Set
- * All necessary synchronization instances will be registered automatically, if required.
- *
- *
- * @param key the thread resource map key
- * @return Returns a thread resource of null if not present
- *
- * @see TransactionalResourceHelper for helper methods to create and bind common collection types
- */
- @SuppressWarnings("unchecked")
- public static
- * All necessary synchronization instances will be registered automatically, if required.
- *
- * @param key
- * @param resource
- */
- public static void bindResource(Object key, Object resource)
- {
- // get the synchronization
- TransactionSynchronizationImpl txnSynch = getSynchronization();
- // bind the resource
- txnSynch.resources.put(key, resource);
- // done
- if (logger.isDebugEnabled())
- {
- logger.debug("Bound resource: \n" +
- " key: " + key + "\n" +
- " resource: " + resource);
- }
- }
-
- /**
- * Unbinds a resource from the current transaction, which must be active.
- *
- * All necessary synchronization instances will be registered automatically, if required.
- *
- * @param key
- */
- public static void unbindResource(Object key)
- {
- // get the synchronization
- TransactionSynchronizationImpl txnSynch = getSynchronization();
- // remove the resource
- txnSynch.resources.remove(key);
- // done
- if (logger.isDebugEnabled())
- {
- logger.debug("Unbound resource: \n" +
- " key: " + key);
- }
- }
/**
* Method that registers a NodeDaoService against the transaction.
@@ -312,11 +198,10 @@ public abstract class AlfrescoTransactionSupport
*/
public static void bindDaoService(TransactionalDao daoService)
{
- // get transaction-local synchronization
- TransactionSynchronizationImpl synch = getSynchronization();
- // bind the service in
- boolean bound = synch.getDaoServices().add(daoService);
+ DAOAdapter adapter = new DAOAdapter(daoService);
+
+ boolean bound = bindListener(adapter, COMMIT_ORDER_DAO);
// done
if (logger.isDebugEnabled())
@@ -337,13 +222,10 @@ public abstract class AlfrescoTransactionSupport
*/
public static void bindIntegrityChecker(IntegrityChecker integrityChecker)
{
- // get transaction-local synchronization
- TransactionSynchronizationImpl synch = getSynchronization();
-
+
// bind the service in
- boolean bound = synch.getIntegrityCheckers().add(integrityChecker);
+ boolean bound = bindListener((TransactionListener) integrityChecker, COMMIT_ORDER_INTEGRITY);
- // done
if (logger.isDebugEnabled())
{
logBoundService(integrityChecker, bound);
@@ -365,12 +247,10 @@ public abstract class AlfrescoTransactionSupport
*/
public static void bindLucene(LuceneIndexerAndSearcher indexerAndSearcher)
{
- // get transaction-local synchronization
- TransactionSynchronizationImpl synch = getSynchronization();
-
- // bind the service in
- boolean bound = synch.getLucenes().add(indexerAndSearcher);
+ LuceneIndexerAndSearcherAdapter adapter = new LuceneIndexerAndSearcherAdapter(indexerAndSearcher);
+ boolean bound = bindListener(adapter, COMMIT_ORDER_LUCENE);
+
// done
if (logger.isDebugEnabled())
{
@@ -379,13 +259,9 @@ public abstract class AlfrescoTransactionSupport
}
/**
- * Method that registers a LuceneIndexerAndSearcherFactory against
+ * Method that registers a Listener against
* the transaction.
- *
- * Setting this will ensure that the pre- and post-commit operations perform
- * the necessary cleanups against the LuceneIndexerAndSearcherFactory.
- *
- * Although bound within a Set, it would still be better for the caller
+ * will be better for the caller
* to only bind once per transaction, if possible.
*
* @param indexerAndSearcher the Lucene indexer to perform transaction completion
@@ -393,13 +269,21 @@ public abstract class AlfrescoTransactionSupport
*/
public static void bindListener(TransactionListener listener)
{
- // get transaction-local synchronization
- TransactionSynchronizationImpl synch = getSynchronization();
-
- // bind the service in
- boolean bound = synch.addListener(listener);
-
- // done
+ boolean bound = false;
+
+ if (listener instanceof IntegrityChecker)
+ {
+ bound = bindListener(listener, COMMIT_ORDER_INTEGRITY);
+ }
+ else if (listener instanceof TransactionalCache)
+ {
+ bound = bindListener(listener, COMMIT_ORDER_CACHE);
+ }
+ else
+ {
+ bound = bindListener(listener, COMMIT_ORDER_NORMAL);
+ }
+
if (logger.isDebugEnabled())
{
logBoundService(listener, bound);
@@ -437,426 +321,5 @@ public abstract class AlfrescoTransactionSupport
{
// No-op
}
-
- /**
- * Gets the current transaction synchronization instance, which contains the locally bound
- * resources that are available to {@link #getResource(Object) retrieve} or
- * {@link #bindResource(Object, Object) add to}.
- *
- * This method also ensures that the transaction binding has been performed.
- *
- * @return Returns the common synchronization instance used
- */
- private static TransactionSynchronizationImpl getSynchronization()
- {
- // ensure synchronizations
- return registerSynchronizations();
- }
-
- /**
- * Binds the Alfresco-specific to the transaction resources
- *
- * @return Returns the current or new synchronization implementation
- */
- private static TransactionSynchronizationImpl registerSynchronizations()
- {
- /*
- * No thread synchronization or locking required as the resources are all threadlocal
- */
- if (!TransactionSynchronizationManager.isSynchronizationActive())
- {
- Thread currentThread = Thread.currentThread();
- throw new AlfrescoRuntimeException("Transaction must be active and synchronization is required: " + currentThread);
- }
- TransactionSynchronizationImpl txnSynch =
- (TransactionSynchronizationImpl) TransactionSynchronizationManager.getResource(RESOURCE_KEY_TXN_SYNCH);
- if (txnSynch != null)
- {
- // synchronization already registered
- return txnSynch;
- }
- // we need a unique ID for the transaction
- String txnId = GUID.generate();
- // register the synchronization
- txnSynch = new TransactionSynchronizationImpl(txnId);
- TransactionSynchronizationManager.registerSynchronization(txnSynch);
- // register the resource that will ensure we don't duplication the synchronization
- TransactionSynchronizationManager.bindResource(RESOURCE_KEY_TXN_SYNCH, txnSynch);
- // done
- if (logger.isDebugEnabled())
- {
- logger.debug("Bound txn synch: " + txnSynch);
- }
- return txnSynch;
- }
-
- /**
- * Cleans out transaction resources if present
- */
- private static void clearSynchronization()
- {
- if (TransactionSynchronizationManager.hasResource(RESOURCE_KEY_TXN_SYNCH))
- {
- Object txnSynch = TransactionSynchronizationManager.unbindResource(RESOURCE_KEY_TXN_SYNCH);
- // done
- if (logger.isDebugEnabled())
- {
- logger.debug("Unbound txn synch:" + txnSynch);
- }
- }
- }
-
- /**
- * Helper method to rebind the synchronization to the transaction
- *
- * @param txnSynch
- */
- private static void rebindSynchronization(TransactionSynchronizationImpl txnSynch)
- {
- TransactionSynchronizationManager.bindResource(RESOURCE_KEY_TXN_SYNCH, txnSynch);
- if (logger.isDebugEnabled())
- {
- logger.debug("Bound txn synch: " + txnSynch);
- }
- }
-
- /**
- * Handler of txn synchronization callbacks specific to internal
- * application requirements
- */
- private static class TransactionSynchronizationImpl extends TransactionSynchronizationAdapter
- {
- private long txnStartTime;
- private final String txnId;
- private final Set