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 extends TransactionSupportUtil
{
/*
* The registrations of services is very explicit on the interface. This
* is to convey the idea that the execution of these services when the
* transaction completes is very explicit. As we only have a finite
* 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
*/
public static final int SESSION_SYNCHRONIZATION_ORDER =
SessionFactoryUtils.SESSION_SYNCHRONIZATION_ORDER - 100;
private static Log logger = LogFactory.getLog(AlfrescoTransactionSupport.class);
/**
*
* @author Derek Hulley
* @since 2.1.4
*/
public static enum TxnReadState
{
/** No transaction is active */
TXN_NONE,
/** The current transaction is read-only */
TXN_READ_ONLY,
/** The current transaction supports writes */
TXN_READ_WRITE
}
/**
* @return Returns the read-write state of the current transaction
* @since 2.1.4
*/
public static TxnReadState getTransactionReadState()
{
if (!TransactionSynchronizationManager.isSynchronizationActive())
{
return TxnReadState.TXN_NONE;
}
// Find the read-write state of the txn
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;
}
else if (TransactionSynchronizationManager.isCurrentTransactionReadOnly())
{
return TxnReadState.TXN_READ_ONLY;
}
else
{
return TxnReadState.TXN_READ_WRITE;
}
}
/**
* Checks the state of the current transaction and throws an exception if a transaction
* is not present or if the transaction is not read-write, if required.
*
* @param requireReadWrite true if the transaction must be read-write
*
* @since 3.2
*/
public static void checkTransactionReadState(boolean requireReadWrite)
{
TxnReadState readState = AlfrescoTransactionSupport.getTransactionReadState();
switch (readState)
{
case TXN_NONE:
throw new IllegalStateException(
"The current operation requires an active " +
(requireReadWrite ? "read-write" : "") +
"transaction.");
case TXN_READ_ONLY:
if (requireReadWrite)
{
throw new IllegalStateException("The current operation requires an active read-write transaction.");
}
case TXN_READ_WRITE:
// All good
}
}
/**
* Are there any pending changes which must be synchronized with the store?
*
* @return true => changes are pending
*
* @deprecated To be replaced by {@link DirtySessionMethodInterceptor}
*/
public static boolean isDirty()
{
Set* This method can be called repeatedly as long as the service being bound * implements equals and hashCode. * * @param daoService */ public static void bindDaoService(TransactionalDao daoService) { DAOAdapter adapter = new DAOAdapter(daoService); boolean bound = bindListener(adapter, COMMIT_ORDER_DAO); // done if (logger.isDebugEnabled()) { logBoundService(daoService, bound); } } /** * Method that registers an IntegrityChecker against the transaction. * Setting this will ensure that the pre- and post-commit operations perform * the necessary cleanups against the IntegrityChecker. *
* This method can be called repeatedly as long as the service being bound * implements equals and hashCode. * * @param integrityChecker */ public static void bindIntegrityChecker(IntegrityChecker integrityChecker) { // bind the service in boolean bound = bindListener((TransactionListener) integrityChecker, COMMIT_ORDER_INTEGRITY); if (logger.isDebugEnabled()) { logBoundService(integrityChecker, bound); } } /** * Method that registers a LuceneIndexerAndSearcherFactory 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 * to only bind once per transaction, if possible. * * @param indexerAndSearcher the Lucene indexer to perform transaction completion * tasks on */ public static void bindLucene(LuceneIndexerAndSearcher indexerAndSearcher) { LuceneIndexerAndSearcherAdapter adapter = new LuceneIndexerAndSearcherAdapter(indexerAndSearcher); boolean bound = bindListener(adapter, COMMIT_ORDER_LUCENE); // done if (logger.isDebugEnabled()) { logBoundService(indexerAndSearcher, bound); } } /** * Method that registers a Listener against * the transaction. *
will be better for the caller * to only bind once per transaction, if possible. * * @param indexerAndSearcher the Lucene indexer to perform transaction completion * tasks on */ public static void bindListener(TransactionListener listener) { 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); } } /** * Use as part of a debug statement * * @param service the service to report * @param bound true if the service was just bound; false if it was previously bound */ private static void logBoundService(Object service, boolean bound) { if (bound) { logger.debug("Bound service: \n" + " transaction: " + getTransactionId() + "\n" + " service: " + service); } else { logger.debug("Service already bound: \n" + " transaction: " + getTransactionId() + "\n" + " service: " + service); } } /** * No-op * * @deprecated No longer does anything */ public static void flush() { // No-op } }