在 JPA/JTA 事务中调用 HTTP 服务 - 事务完整性
我有一个 JSF/EJB/JPA 应用程序,它使用容器管理的持久性。有 一种情况是通过 HTTP 调用外部服务,这是有成本的,这 成本被分配回请求用户。在当前的实现中 发出 HTTP 请求的过程是由定期运行的 EJB 计时器方法执行的 在后台。
尽管计时器方法可能必须在一次调用中处理多个请求 每个请求都需要独立处理,独立分配 也就是说,成本返还给用户。如果用户 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 调用,然后在出现任何错误时向用户贷记 发生了,但没有交易完整性。
这对我来说是新领域,任何人都可以指出我正确的方向吗? 做我想做的事情的既定方式?
非常感谢。
ps 我正在使用 glassfish 3.1 堆栈和 Seam 3
I have a JSF/EJB/JPA application which uses container managed persistence. There is
one case where a call is made to an external service via HTTP which has a cost, this
cost being allocated back to the requesting user. In the current implementation the
process of making the HTTP request is performed by a EJB timer method running periodically
in the background.
The timer method may have to deal with a number of requests in one invocation, although
each request needs to be treated independently, independently with respect to allocating
the cost back to the user, that is. If user A doesn't have enough credit to purchase a
book, this musn't prevent the successful purchase of a book by user B resulting in their
balance being debited due to a rollback.
To provide control over the transaction demarcation for independent processing of each
request I'm using bean managed transactions for the class in which the timer method
resides. This is a java-pseudo-code version of what I've got now:
@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();
}
}
}
So the idea is that I start a transaction, assume success and debit the cost from the
user, call the http service and commit if it succeeds or rollback otherwise.
I have an uneasy feeling that I may not be anywhere near the right ballpark with this
design, particularly having the lengthy http call (actually done using jax-rs) inside
the pessimistic_write transaction. I wondered if I could firstly, within a transaction
debit the user (begin/debit/commit), make http call, then credit the user if any error
happens, but there's no transaction integrity.
This is new territory for me, can anyone point me in the right direction, is there an
established way of doing what I'm trying to do?
Many Thanks.
p.s. I'm using a glassfish 3.1 stack with Seam 3
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我不确定 jax-rs 通信层如何。如果通信是单线程的,那么您编写的代码是一个长时间运行的事务。这可能会使您的应用程序变慢。
我不是技术专家,但我可以建议的是 -
记入帐户并在线程上进行 jax-rs 调用。在这种情况下,事务将在将调用发送到远程节点之前关闭。而且它不会是一个长时间运行的事务,因此应用程序会更快。
I am not sure how jax-rs communication layer is. if the communication is single threaded, then the code you have written is a long running transaction. which might make your application slower.
I am not a tech guru, but what i can suggest is -
Credit the account and make the jax-rs call on a thread. on that case the transaction will be closed before sending the call to remote node. and it will not be a long running transaction, so the application will be faster.