Главная > Soft > rollback() vs setRollbackOnly()

rollback() vs setRollbackOnly()

Вот и случился постыдный баг на WAS6: пользователь видит вот такое сообщение вместо реальной ошибки. Особенно противно, когда понимаешь, что это сделал ты из-за своей лени, просто не хотелось проверять это место и вот результат.

…
java.lang.IllegalStateException
>> at com.ibm.ejs.container.BMStatelessBeanO.setRollbackOnly(BMStatelessBeanO.java:69)
…

Небольшой пример кода, где происходит ошибка

this.context.setRollbackOnly(); //Баг
logger.info(“Some error"));
throw new Exception("Some error");

Первым делом проверил настройку транзакций. Выяснилось, этот кусок прекрасно работает для Container-Managed Transaction (CMT), но падает в Bean-Managed Transactions (BMT).

После обращения к документации стала ясна и вся суть проблемы.

Для управления транзакциями в EJB есть интерфейс EJBContext, который может возвращать интерфейс UserTransaction.

В случае BMT управление транзакцией ложится на программиста и UserTransaction: Он полностью отвечает за начало её и завершение в виде commit или rollback.

@Stateless
@TransactionManagement( TransactionManagementType.BEAN )
public class ExampleSessionFacade implements IExampleSessionFacadeLocal {
  @Resource
  private EJBContext context;
  //Наш метод
  public void trxnMethod() throws Exception {
    UserTransaction utx = context.getUserTransaction();
    //try-catch блок
    try {
      utx.begin();
      …
      utx.commit();
    } catch(Throwable t) {
      utx.rollback();
      throws new Exception(t.getMessage());
    }
  }
}

В случае CMT за управление транзакцией отвечает контейнер. Тот сам делает commit или rollback, когда это необходимо. Но что, если нужно сделать rollback, но при этом не заканчивать выполнение сразу? В этом случае и используется EJBContext и setRollbackOnly().

@Stateless
public class ExampleSessionFacade implements IExampleSessionFacadeLocal {
  @Resource
  private EJBContext context;
  public void someTrxnMethod() throws Exception {
    try {
      …
    } catch(Throwable t) {
      context.setRollbackOnly();
    }
  }
}

Oracle советует не использовать UserTransaction.setRollbackOnly и EJBContext.setRollbackOnly в BMT, так как поведение методов непредсказуемо и зависит от реализации контейнера, и использовать только EJBContext.setRollbackOnly() в CMT.

Итого:

Код был переписан, чтоб выполнять setRollbackOnly только в случает CMT, но не BMT.

Categories: Soft Tags: , ,
  1. Пока что нет комментариев.
  1. Пока что нет уведомлений.