Что RetryTransactionHandler работает в Alfresco - PullRequest
2 голосов
/ 31 июля 2011

Alfresco сообщит программисту, как только вам нужно будет выполнить транзакцию в репозитории, чтобы использовать RetriedTransactionHandler для выполнения транзакции.

Кто-нибудь может дать мне разъяснение по поводу этого?

В частности, я говорю о таком коде

RetryingTransactionCallback<String> callback = new RetryingTransactionCallback<String>(){
 public String execute() throws Throwable {
     // doProcess must be invoked within user context.
 AuthenticationUtil.runAs(new RunAsWork<String>(){
 public String doWork()throws Exception{
 try {      
     if(getOperationType().equals(OperationTypes.CREATE_ORGANIZATION_OPERATION)){
 RetryingTransactionHelper txnHelper = 
     Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
     txnHelper.doInTransaction(doProcessActionCallbackOperations.CreateOrganizationCallback, false, true);
                        }
                    } catch(Throwable e){

                    }
                    return "";
                }
            }, AuthenticationUtil.getSystemUserName());
            return "";
        }
    };  
    try {
        RetryingTransactionHelper txnHelper = Repository.getRetryingTransactionHelper(FacesContext.getCurrentInstance());
        txnHelper.doInTransaction(callback, false, true);
    } catch (Throwable e) {
        if (e instanceof ReportedException == false) {
            Utils.addErrorMessage(formatErrorMessage(e), e);
        }
        ReportedException.throwIfNecessary(e);
    }

Кроме того, как вы заметили, я использую AuthenticationUtils.runAs ().

Так вы можете помочь мне понять различные ключи в этом коде, такие как RetryTransaction & AuthenticationUtils?

Ответы [ 2 ]

5 голосов
/ 31 июля 2011

RetryingTransactionHelper гарантирует, что предоставленное вами callback будет выполнено в транзакции.Более того, как следует из названия, если транзакция завершается неудачей по каким-то причинам (например, в коде callback возникает исключение, которое неправильно перехвачено, или вы пытаетесь изменить одно и то же содержимое в хранилище одновременно из двух разных потоков),та же транзакция будет правильно откатана и повторно выполнена («повторена») настраиваемое количество раз (по умолчанию: 20).Это удобнее, чем ручная обработка транзакций чаще, чем нет.

В размещенном вами коде вы вкладываете вызов doProcessActionCallbackOperations.CreateOrganizationCallback в две транзакции (поскольку последний параметр doInTransaction всегда true, т.е. requiresNew), внешнее существо, созданное до выполнения callback, внутреннее, созданное в самом callback.Мне кажется, что вы могли бы избавиться от внутренней транзакции, но это ваше дело.Транзакции могут быть вложенными, даже если сбои во внутренней транзакции, скорее всего, сделают недействительным весь стек транзакций.

Средство AuthenticationUtils.runAs позволяет вам выполнять фрагменты логики, используя полномочия вВообще отличается от текущего пользователя.Внутренне учетные данные пользователя хранятся в виде ThreadLocal параметров.В вашем случае AuthenticationUtil.runAs позаботится о временном изменении такого ThreadLocal, чтобы позволить внутреннему обратному вызову всегда выполняться с самым высоким уровнем разрешений (т. Е. Системой) независимо от того, какой пользователь выполняет код.Существуют также ситуации, когда в данный момент не зарегистрирован пользователь, например, в рамках запланированных заданий.Затем AuthenticationUtils.runAs позволяет вам получить доступ к содержимому в хранилище, обычно указывая system или admin пользователей.

4 голосов
/ 30 июля 2014

Просто чтобы прояснить это немного, RetriedTransactionHelper будет повторять операцию, только если выброшенное исключение имеет определенный тип.Главным образом исключения, относящиеся к тому, чтобы быть проигравшим в ситуации параллелизма:

 /**
 * Exceptions that trigger retries.
 */
@SuppressWarnings({ "rawtypes" })
public static final Class[] RETRY_EXCEPTIONS;
static
{
    Class<?>[] coreClasses = new Class[] {
                ConcurrencyFailureException.class,
                DeadlockLoserDataAccessException.class,
                StaleObjectStateException.class,
                JdbcUpdateAffectedIncorrectNumberOfRowsException.class,     // Similar to StaleObjectState
                LockAcquisitionException.class,
                ConstraintViolationException.class,
                UncategorizedSQLException.class,
                SQLException.class,
                BatchUpdateException.class,
                DataIntegrityViolationException.class,
                StaleStateException.class,
                TooManyResultsException.class,              // Expected one result but found multiple (bad key alert)
                ObjectNotFoundException.class,
                CacheException.class,                       // Usually a cache replication issue
                SQLGrammarException.class, // Actually specific to MS SQL Server 2005 - we check for this
                LockTryException.class
                };

Я думаю, этого достаточно, когда одна из этих транзакций находится в стеке исключений, а не обязательно является последней.Я также думаю, что вы можете избежать повторных попыток, установив исключение, которое реализует интерфейс org.alfresco.repo.transaction.DoNotRetryException.

...