Вызов службы HTTP в транзакции JPA/JTA - целостность транзакции

У меня есть приложение JSF/EJB/JPA, которое использует управляемое контейнером постоянство. В одном случае выполняется вызов внешней службы по протоколу HTTP, которая имеет свою стоимость, и эта стоимость возвращается обратно запрашивающему пользователю. В текущей реализации процесс создания HTTP-запроса выполняется методом таймера EJB, периодически выполняющимся в фоновом режиме.

Способу таймера может потребоваться обработать несколько запросов в одном вызове, хотя каждый запрос должен обрабатываться независимо, независимо от распределения затрат обратно пользователю, то есть. Если у пользователя A недостаточно средств для покупки книги, это не помешает успешной покупке книги пользователем B, в результате чего его баланс будет списан из-за отката.

Чтобы обеспечить контроль над разграничением транзакций для независимой обработки каждого запроса, я использую управляемые компонентом транзакции для класса, в котором находится метод таймера. Это версия Java-псевдокода того, что я получил сейчас:

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class MessageTimer {
  private void processMessages(UserMessage msg) {
    tx.begin();
    em.joinTransaction();

    try {
      userData = em.find(..., PESSIMISTIC_WRITE);

      if(user has enough credit) {
        debit cost from user;

        status = make external http request to order book from supplier;
        if(status == success) {
          commit = true;
        }
      }
    } catch(Exception) {
      tx.rollback();
    }

    if(commit) {
      tx.commit();
    }
    else {
      tx.rollback();
    }
  }
}

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

У меня есть неприятное ощущение, что я не могу быть где-то рядом с подходящим эталоном с этим дизайном, особенно с длительным http-вызовом (фактически сделанным с использованием jax-rs) внутри транзакции pessimistic_write. Мне было интересно, смогу ли я, во-первых, в рамках транзакции дебетовать пользователя (begin/debit/commit), сделать http-вызов, затем кредитовать пользователя, если произойдет какая-либо ошибка, но нет целостности транзакции.

Это новая территория для меня, кто-нибудь может указать мне правильное направление, есть ли установленный способ делать то, что я пытаюсь сделать?

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

PS Я использую стек Glassfish 3.1 с Seam 3

1 ответ

Я не уверен, каков уровень коммуникации Jax-RS. если связь однопоточная, то написанный вами код является долго выполняющейся транзакцией. что может сделать ваше приложение медленнее.

Я не технический гуру, но я могу предложить следующее:

Пополните счет и сделайте вызов jax-rs в потоке. в этом случае транзакция будет закрыта до отправки вызова на удаленный узел. и это не будет длительной транзакцией, поэтому приложение будет работать быстрее.

Другие вопросы по тегам