Вызов службы 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 в потоке. в этом случае транзакция будет закрыта до отправки вызова на удаленный узел. и это не будет длительной транзакцией, поэтому приложение будет работать быстрее.