Developing repo actions in Alfresco 5.1

Recently I’ve been told about an issue in our software related to a custom action which was modifying a NodeRef created inside the current transaction.

In Alfresco Share, a rule on a folder can be configured to execute an action by selecting two different modes:

  • Run in background
    • The action is executed in a new thread
    • The new thread creates a new transaction for execution, so any other transaction modifying the node (as rendition operations on brand new nodes) should provoke a ConcurrencyFailureException
    • It’s required to use a RetryingTransactionHelper to avoid this kind of conflicts
  • Run in foreground
    • The action is executed within the current thread and within the current transaction
    • No special code is required to perform modifications on the node, as no ConcurrencyFailureException will arise

If this condition could be detected, a code for each situation could be developed. However, I’ve found an issue with Alfresco API and there is no way to know if the action is being executed synchronously or asynchronously.

I’ve created the following pattern to cover both behaviors with the same code.


public class CustomAction extends ActionExecuterAbstractBase {

    @Override
    protected void executeImpl(Action action, NodeRef actionedUponNodeRef) {

        try {
            executeInNewTransaction(actionedUponNodeRef);
        } catch (Throwable throwableNewTransaction) {
            executeImplInternal(actionedUponNodeRef);
        }

    }

    // Avoid ConcurrencyFailureException by using RetryingTransactionHelper
    private void executeInNewTransaction(final NodeRef nodeRef) {
        
        RetryingTransactionCallback<Void> callback = new RetryingTransactionCallback<Void>() {
            @Override
            public Void execute() throws Throwable {
                executeImplInternal(nodeRef);
                return null;
            }
        };
        RetryingTransactionHelper txnHelper = transactionService.getRetryingTransactionHelper();
        txnHelper.doInTransaction(callback, false, true);
    }

    private void executeImplInternal(NodeRef actionedUponNodeRef) {
       // Do whatever you need with the current transaction
    }

}

Obviously it’s not the better solution in terms of performance, but it works for both scenarios.

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s