コンテナ管理の永続性を使用する JSF/EJB/JPA アプリケーションがあります。コストのある HTTP を介して外部サービスへの呼び出しが行われるケースが 1 つあります。このコストは、要求元のユーザーに割り当てられます。現在の実装では、HTTP 要求を作成するプロセスは、バックグラウンドで定期的に実行される EJB タイマー メソッドによって実行されます。
タイマー メソッドは、1 回の呼び出しで多数の要求を処理する必要がある場合がありますが、各要求は個別に、ユーザーへのコストの割り当てに関して個別に処理する必要があります。ユーザー 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 サービスを呼び出して、成功した場合はコミットするか、そうでない場合はロールバックするという考え方です。
私は、特に pessimistic_write トランザクション内で長い http 呼び出し (実際には jax-rs を使用して行われる) があるため、この設計では正しい球場の近くにいないのではないかと不安に思っています。最初に、トランザクション内でユーザーのデビット (begin/debit/commit) を行い、http 呼び出しを行い、エラーが発生した場合にユーザーにクレジットを与えることができるかどうか疑問に思いましたが、トランザクションの整合性はありません。
これは私にとって新しい領域です。誰かが私を正しい方向に向けることができますか?私がやろうとしていることを行うための確立された方法はありますか?
どうもありがとう。
ps Seam 3でglassfish 3.1スタックを使用しています