在JPA/JTA事务中调用HTTP服务 - 事务完整性
我有一个使用容器管理持久性的JSF/EJB/JPA应用程序。有一种情况是通过HTTP向外部服务发起呼叫,其中有一个费用,这个费用被分配回请求用户。在当前实现中,通过在后台定期运行 的EJB定时器方法执行进行HTTP请求的过程。在JPA/JTA事务中调用HTTP服务 - 事务完整性
计时器方法可能不得不在一次调用中处理多个请求,但每个请求需要独立处理,独立于将 成本分配给用户,也就是说。如果用户A没有足够的积分购买 书籍,则这阻止了用户B成功购买了书籍,导致其 余额因回滚而被扣除。
为了对每个 请求的独立处理提供对事务分界的控制,我对定时器方法 所在的类使用bean管理事务。这是什么,我现在已经有了一个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交易。我想知道是否可以首先在交易 借记用户(开始/借记/提交),进行http呼叫,然后在发生任何错误 时扣除用户,但没有交易完整性。
对我来说,这是一个新的领域,任何人都可以指出我正确的方向,有没有一个 做我想做的事情?
很多谢谢。
p.s.我正在使用Seam 3的glassfish 3.1堆栈
我不知道jax-rs通信层是如何的。如果通信是单线程的,那么你写的代码是一个长时间运行的事务。这可能会让你的应用程序变慢。
我不是一个技术大师,但我可以建议是 -
信用账户,使JAX-RS调用一个线程。在这种情况下,在将呼叫发送到远程节点之前,交易将被关闭。它不会是一个长时间运行的事务,所以应用程序会更快。
嗨,我在EJB容器中运行,所以不能使用我认为的线程。我需要http调用的结果来确定是否发生了成本,所以我不确定我有什么选项。这是一个长期运行的交易,当然,但我没有看到它的方式。 – Oversteer 2011-05-28 11:37:49