0

私はサードパーティのシステムに顧客をプロビジョニングする典型的なエンタープライズアプリケーションを開発しました。このシステムには、特定の顧客に対して1つのスレッドしか動作できないという制限があります。そこで、現在進行中のcustomerIdsのSetを含む@Singletonで構成される単純なロック機構を追加しました。新しい要求がプロビジョニングのために来るときはいつも、これはSetをチェックします。 cusotomerIdが存在する場合は、それ以外の場合はSetに追加して処理に移ります。別々のEJBメソッドでのトランザクションの開始/終了

最近では、このアプリケーションがクラスタ化されており、このロックアプローチはもはや有効ではないということが決定されました。私たちは、ロックのためにDBを使用する解決策を考え出しました。 customerIdsを含む単一の列を持つテーブルを作成しました(これには固有の制約もあります)。新しいプロビジョニングリクエストが発生すると、トランザクションを開始し、SELECT FOR UPDATEというcustomerIdを持つ行をロックしようとします(customerIdがまだ存在しない場合は挿入します)。その後、顧客のプロビジョニングを開始し、完了したらトランザクションをコミットします。 概念は機能しますが、トランザクションに問題があります。現在CustomerLockadd()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); 
    } 
} 
+0

なぜ「取引の開始と終了は同じ方法で行われなければならない」と思いますか?最終的にブロックBTWにはかなり奇妙なコミットコールがあります。すべてがうまくいくと(例外はスローされません)、それはトランザクションをコミットし、DBロックはこれまで(トランザクション全体で)消えます。 – user3714601

+0

申し訳ありません...「最終的に」そこにいることはありませんでした:)コードを修正しました。 – goggy

+0

Excerpt = snippet、それらは通常十分詳細ではありません。 "CustomerProvisioning"とは何ですか?別のEJB? – Gimby

答えて

0

、あなたは混在させることはできませんコンテナ管理およびbean-管理されたトランザクション。 StandardCustomerProvisionerには@TransactionManagement(TransactionManagementType.BEAN)のようなアノテーションはないため、コンテナ管理のトランザクションを使用し、デフォルトではREQUIREDを使用します。

あなたはそれを動作させるために2つのオプションがあります:

1)のUserTransaction呼び出しで "@TransactionManagement(TransactionManagementType.BEAN)" を削除し、CMT

2を実行するには)この注釈(「@TransactionManagementを(追加しますTransactionManagementType.BEAN)」)をStandardCustomerProvisionerに追加し、このメソッドからのトランザクションマークアップ呼び出しを使用するため、呼び出されるメソッドはすべて同じトランザクションコンテキストを使用します。とにかくCustomerLockからのマークアップコールを削除する必要があります。

+0

遅い回答に申し訳ありません...はい、私はこの取引がコンテナでどのように機能するかについて完全に誤解していました。上記の解決策を実現するためには、数ヵ月後にしか考えていない。私はちょうど少し 'ブレーンストーミング'が必要だと思う:)返信のためにすべてありがとう!乾杯 – goggy

関連する問題