私はサードパーティのシステムに顧客をプロビジョニングする典型的なエンタープライズアプリケーションを開発しました。このシステムには、特定の顧客に対して1つのスレッドしか動作できないという制限があります。そこで、現在進行中のcustomerIdsのSet
を含む@Singleton
で構成される単純なロック機構を追加しました。新しい要求がプロビジョニングのために来るときはいつも、これはSet
をチェックします。 cusotomerIdが存在する場合は、それ以外の場合はSet
に追加して処理に移ります。別々のEJBメソッドでのトランザクションの開始/終了
最近では、このアプリケーションがクラスタ化されており、このロックアプローチはもはや有効ではないということが決定されました。私たちは、ロックのためにDBを使用する解決策を考え出しました。 customerIdsを含む単一の列を持つテーブルを作成しました(これには固有の制約もあります)。新しいプロビジョニングリクエストが発生すると、トランザクションを開始し、SELECT FOR UPDATE
というcustomerIdを持つ行をロックしようとします(customerIdがまだ存在しない場合は挿入します)。その後、顧客のプロビジョニングを開始し、完了したらトランザクションをコミットします。 概念は機能しますが、トランザクションに問題があります。現在CustomerLock
のadd()
とremove()
のメソッドがあり、Set
からcustomerIdsを追加したり削除したりしています。このクラスをBean管理のトランザクションを持つステートレスなEJBに変換したいと思っていました。 add()
メソッドはトランザクションを開始し、行をロックしますが、remove()
メソッドはトランザクションをコミットして行をロック解除します。しかし、トランザクションの開始と終了は同じ方法で行われなければならないと思われます。私が記述したアプローチを使用する方法はありますか、トランザクションを開始して同じメソッドで終了するようにロジックを変更する必要はありますか?
CustomerLockクラス:
@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class CustomerLock {
@Resource
private UserTransaction tx;
public void add(String customerId) throws Exception {
try {
tx.begin();
dsApi.lock()
} catch (Exception e) {
throw e;
}
}
public void remove(String customerId) throws Exception {
try {
tx.commit();
} catch (Exception e) {
throw e
}
}
}
CustomerProvisionerクラスの抜粋:
public abstract class CustomerProvisioner {
...
public void execute(String customerId) {
try {
customerLock.add(customerId);
processing....
customerLock.remove(customerId);
} catch (Exception e) {
logger.error("Error", e);
}
}
...
}
StandardCustomerProvisionerクラス:
@Gimbyが指摘したように@Stateless
public class StandardCustomerProvisioner extends CustomerProvisioner {
...
public void provision(String customerId) {
// do some business logic
super.execute(customerId);
}
}
なぜ「取引の開始と終了は同じ方法で行われなければならない」と思いますか?最終的にブロックBTWにはかなり奇妙なコミットコールがあります。すべてがうまくいくと(例外はスローされません)、それはトランザクションをコミットし、DBロックはこれまで(トランザクション全体で)消えます。 – user3714601
申し訳ありません...「最終的に」そこにいることはありませんでした:)コードを修正しました。 – goggy
Excerpt = snippet、それらは通常十分詳細ではありません。 "CustomerProvisioning"とは何ですか?別のEJB? – Gimby