Транзакция не активная исключительная ситуация - EJB Transaction State - PullRequest
2 голосов
/ 30 января 2012

У меня проблема с компонентами EJB, которые отвечают за запуск транзакции.Я использую Jboss 5.01.

По сути, я хотел бы выполнить данный код после того, как была совершена конкретная транзакция.конкретный код также включает вызов компонента EJB, который выполняет свои собственные транзакции.

Чтобы убедиться, что мой код выполняется после фиксации предыдущей транзакции, я зарегистрировал компонент синхронизации в компоненте транзакции:

Transaction tx = transactionManager.getTransaction();
tx.registerSynchronization(new CallbackSynchronization());

Реализация Synchronizaton в основном делает следующее:

class CallbackSynchronization implements Synchnronization {

    private AccountService service;  // This is a Stateless session bean

    public CallbackSynchronization(AccountService service) {
        this.service   = service;
    }

    public afterCompletion(int status) {
        if(Status.STATUS_COMMITTED == status) {
            service.deleteAccounts();
        }
    }
}

Проблема в том, что когда я вызываю service.deleteAccounts(), я получаю исключение, которое в итоге говорит мне, что транзакция не активна.

И это то, что меня смущает.EJB с методами, отмеченными @TransactionAttribute(TransactionAttributeType.REQUIRED), создаст новую транзакцию, если она не активна (REQUIRED является значением по умолчанию в JBOSS).

Почему тогда я получаю "Транзакция не активна"?

Большое спасибо,

Янив

1 Ответ

3 голосов
/ 01 февраля 2012

Проблема в том, что исходная транзакция, которую вы запустили, по-прежнему связана с потоком (даже если она находится в состоянии COMMITTED).Одно из существенных различий между использованием Transaction и TransactionManager заключается в том, что более поздние commit () и rollback () не будут ассоциироватьсятранзакция из потока.Чтобы процитировать из javadoc для обоих методов:

Когда этот метод завершается, поток больше не связан с транзакцией.

Есть два способа справиться с этим (и я в общих чертах обрисовал их в общих чертах, которые вы, возможно, захотите немного уточнить).

Вариант 1. Выполните откат или фиксацию для менеджера транзакций (в блоке try, потому что он потерпит неудачу).

public afterCompletion(int status) {
  if(Status.STATUS_COMMITTED == status) {
    try { transactionManager.rollback(); } catch (Throwable t) {}
    service.deleteAccounts();
  }
}

Вариант 2: Начните новую транзакцию, которая будет удовлетворять атрибуту REQUIRED вашего EJB, предварительно запустив транзакцию, но вам нужно остаться и управлять ею, которая становится липкой.

public afterCompletion(int status) {
  if(Status.STATUS_COMMITTED == status) {
    try { 
      transactionManager.begin();
      service.deleteAccounts();
      transactionManager.commit();
    } catch (Exception e) {
        // ... handle exception here
    }
  }
}

Вариант 3. Самым чистым вариантом может быть пометка метода EJB как REQUIRES_NEW , поскольку это заставит контейнер EJB начать новую транзакцию.

...