サンプル 4b:分散型トランザクションと CMP

サンプル 4b は、server1server2 を使用した分散型 2 フェーズ コミット トランザクション管理の使用法を示しています。また、このサンプルは、EjbClient.java および BalanceBean.java に含まれている save および spend メソッドの実装で示されているとおり、クライアント区分トランザクションとコンテナ管理トランザクションの両方を使用します。


メモ

このサンプルはリレーショナル データベースを使用しますが、独創的な動作はしませ ん (スキーマについては、第 7 章の「サンプル 2」セクションを参照してください)。 サンプル 4b を実行するには、複数の接続をサポートしているデータベースとドライ バを使用する必要があります。特定のデータ ソース フォーマットに従って、使用して いるデータソース情報を deploy.properties ファイルに追加します。


最初に META-INF/ejb-jar.xml ファイルを開き、次の env-entry 要素を調べます。

JRun のルート ディレクトリ/samples/sample4b ディレクトリにある deploy2.properties ファイルを調べます。deploy2.properties ファイルは、server2 により使用されます。次のエントリに注意してください。

sample4b.BalanceHome.maxValue=1000
sample4b.BalanceHome.minValue=-1000

これらの 2 つのプロパティは、残高の有効範囲を指定します。server2 における最小値は -1000、最大値は 1000 です。最小値または最大値に達すると、例外となります。Server2BalanceBean は、残高をプロパティ ファイルに設定されている値と照合してチェックします。server2 で制限を超えると例外となり、server1 でもトランザクションがロールバックされます。

詳細については、『JRun によるアプリケーションの開発』を参照してください。

JNDI コンテキストのカスタマイズ

まず、呼び出しをより単純に、また理解しやすくするために JNDI コンテキストをカスタマイズします。JRun のルート ディレクトリ/samples/sample4b/client ディレクトリに移動して EjbClient.java ファイルを開きます。login メソッドにより、クライアントがポート 2323 (server1) でリスニングしているサーバへの context 参照を設定した場所が確認できます。次に、クライアントは、ポート 2324 (server2) で受信しているサーバに対する context 参照を設定し、sample4b.BalanceHomeBalanceHome2 に結合します。次の図に示すように、これによって "server1" の
sample4b.BalanceHome と "server2"の sample4b.BalanceHome を区別します。

クライアント区分トランザクション

EjbClient.javasave メソッドに注目してください。server1 および server2 の残高は save メソッドによって更新されます。save は 2 つの Balance インスタンスを作成します。これらは各サーバにそれぞれ関連付けられます。transaction.begin を実行します。これは公開記述子の save.ejb.transactionAttribute 設定に必要です。

次に EjbClient.save メソッドは、Balance の両方のインスタンスに対して save(amount) を呼び出します。いずれかの呼び出しで例外が発生した場合、トランザクションがロールバックされ、両方のサーバの残高が更新されません。例外が発生しない場合は、transaction.commit が呼び出されます。そのため、server2 で残高が最小値または最大値に達すると、transaction.rollback が呼び出されて server1server2 の同期を取ります。

暗黙トランザクション

EjbClient.javaspend メソッドを調べます。EjbClient.javasave メソッドはサーバごとに BalanceBean.save を呼び出したのに対し、EjbClient.javaspend メソッドは BalanceBean.spend を一度だけ呼び出します。BalanceBean.spend は、登録されている別の BalanceBean を検索するためです。見つかると、BalanceBean.spend メソッドが呼び出されます。

次は、JRun のルート ディレクトリ/samples/sample4b/ejbeans/BalanceBean.java ファイルの spend メソッドに注目してください。spend メソッドは自らの残高を更新しますが、次のコードの抜粋のとおり、server2 の残高も更新します。

if (_balance2 != null)
{
_balance2.spend(value);
}

server1 がどのように server2 を認識するかを理解するには、BalanceBean.connect メソッドに注目します。次のコードが表示されます。

...
try
  {
    Properties environment = _context.getEnvironment();
    String host =
      environment.getProperty(EjiptProperties.CLASS_SERVER_HOST);
    int port =
      Integer.parseInt(environment.getProperty("balance2Port"));
    Properties properties = new Properties();
    properties.setProperty(Context.INITIAL_CONTEXT_FACTORY,
      "allaire.ejipt.ContextFactory");
    properties.setProperty(Context.PROVIDER_URL, "ejipt://" + host +
      ":" + port);
    BalanceHome home = 
      (BalanceHome)(new InitialContext(properties)).lookup
        ("sample4b.BalanceHome");
    _balance2 = createBalance(home, 123);
    }
    catch (NumberFormatException format)
    {
      // ポート情報なし、接続は不要です。
    }
    catch (Exception exception)
    {
      ResourceManager.getLogger().logException
        ("Failed to contact other server", exception);
    }
...

このコードは、関連する deploy.properties ファイルで、balance2Port という名前のプロパティをチェックします。JRun のルート ディレクトリ/samples/sample4b にあるdeploy.properties ファイルには、次のエントリが含まれています。

sample4b.BalanceHome.balance2Port=2324

コードで createBalance を呼び出します。これによって server2 のリモート インターフェイスへの参照が返されます。BalanceBean.getBalance2 メソッドは、ポート 2324 で受信しているサーバ (以前 server2 として参照された) の BalanceHome に対する参照を単に取得します。

複数のサーバ インスタンス

make ファイルは、ejipt.ejbDirectory プロパティを使用して、第 2 のサーバ インスタンスの /deploy および /runtime ディレクトリを指定します。

サンプルを実行するには、コマンド プロンプトを開いて RMID のシェルを起動します (このサンプルはフェイルセーフ モードで実行するので RMID が必要です)。環境変数を設定し、次のコマンドを入力して RMID を開始します。

bash$ make rmid

別のコマンド プロンプトとシェルを開きます。次のコマンドを入力します。

bash$ make jars 
bash$ make deploy2
bash$ make start2.

make deploy2 および make start2 コマンドは、両方のサーバを展開または起動します。次に make run を実行してクライアントを起動します。サンプルが終了したら、make stop2 を実行して両方のサーバを停止してください。