Sun ONE ロゴ     前へ      目次      索引      次へ     
Sun ONE Application Server 7 サーバーアプリケーションの移行および再配備



付録 C

EJB 1.1 から EJB 2.0 への移行

Sun ONE Application Server 7 でも EJB 1.1 仕様は引き続きサポートされますが、その拡張機能を活用するため、EJB 2.0 アーキテクチャの使用をお勧めします。

EJB 1.1 を EJB 2.0 へ移行するには、コンポーネントのソースコード内部を含め、多くの修正が必要です。

基本的に、必要とされる修正は、EJB 1.1 と EJB 2.0 の間の相違に関連しています。これらの相違のすべてについて、次の各項目で説明します。

EJB クエリ言語

EJB 1.1 仕様には、個別のアプリケーションサーバーに対する検索メソッドのクエリを形成し、記述する方法および言語が残されています。多くのアプリケーションサーバーのベンダーは、開発者が SQL を使用してクエリを作成するよう求めますが、一方で、特定のアプリケーションサーバー製品に固有の、独自の専用言語を使用する場合もあります。このようにクエリの実装が混在しているため、アプリケーションサーバー間の不整合が生じています。

EJB 2.0 仕様では、これらの不整合および不備を修正した EJB Query Language、または EJB QL と呼ばれるクエリ言語が導入されています。EJB QL は、SQL92 に基づいています。EJB QL は、検索と選択メソッドの両形式で、特にコンテナ管理による持続性を使用したエンティティ Beans 用にクエリメソッドを定義します。SQL に対する EJB QL の主な長所は、EJB コンテナを通じた移植性と、エンティティ Beans の関係をナビゲートする機能にあります。

ローカルインタフェース

EJB 1.1 アーキテクチャでは、セッション Beans およびエンティティ Beans にリモートインタフェースという 1 つのインタフェースタイプがあり、そのインタフェースを通じて、クライアントや他のアプリケーションコンポーネントからのアクセスが可能になります。リモートインタフェースは、Bean インスタンスにリモート機能があるものとして設計されています。Bean は RMI からそれを継承し、ネットワークを通じて分散クライアントとやり取りを行うことができます。

EJB 2.0 では、セッション Beans およびエンティティ Beans はクライアントにメソッドを公開するインタフェースを 2 種類利用できます。1 つはリモートインタフェース、もう 1 つはローカルインタフェースです。2.0 リモートインタフェースは、1.1 アーキテクチャで使用されているリモートインタフェースと同じものです。Bean は RMI からリモートインタフェースを継承し、ネットワーク層を通じてそのメソッドを公開します。また、分散クライアントとやり取りするための同一の機能を備えています。

ただし、セッションおよびエンティティ Beans 用のローカルインタフェースは、ローカルクライアント、つまり同一の EJB コンテナに共存しているクライアントである EJB からの軽量アクセスをサポートしています。EJB 2.0 仕様では、さらに、ローカルインタフェースを使用した同一アプリケーション内にある EJB を必要とします。つまり、ローカルインタフェースを使用したアプリケーションの EJB 用の配備記述子が、1 つの ejb-jar ファイルに含まれている必要があります。

ローカルインタフェースは、標準 Java インタフェースです。これは、RMI からは継承されません。Enterprise JavaBeans は、ローカルインタフェースを使用して、同一コンテナ内にある他の Beans にメソッドを公開します。ローカルインタフェースを使用することにより、Bean はクライアントと緊密に連携でき、リモートメソッド呼び出しのオーバーヘッドなしに直接アクセスが可能になります。

さらに、ローカルインタフェースは、参照セマンティクスにより Beans 間で渡される値を許可します。この方法では、オブジェクト自体ではなくオブジェクトへの参照を渡すため、大量のデータを持つオブジェクトを渡す際に発生するオーバーヘッドが軽減し、パフォーマンス上の利点があります。

リモートインタフェースではなくローカルインタフェースを使用すると、セッションまたはエンティティ Bean の設定は簡単になります。クライアントに公開されている Bean のメソッド経由のローカルインタフェースは、EJBObject ではなく EJBLocalObject を拡張します。同様に、Bean のホームインタフェースは、EJBHome ではなく EJBLocalHome を拡張します。実装クラスは、同じ EntityBean または SessionBean インタフェースを拡張します。



EJB 2.0 でリモートに予定されている Bean は、リモートインタフェースで EJBObject を、ホームインタフェースで EJBHome を、EJB 1.1 の場合と同様に拡張します。



EJB 2.0 コンテナ管理による持続性 (CMP)

EJB 2.0 仕様では、CMP を拡張し、CMP 間で関係のある複数のエンティティ Beans を許可します。これは、コンテナ管理による関係 (CMR) と呼ばれます。コンテナでは、関係と、関係の参照整合性を管理します。

EJB 1.1 仕様で提示されていた CMP モデルは、より制限の多いものでした。1.1 アーキテクチャでの CMP は、データベースやリソースマネージャタイプから独立したデータアクセスに制限されていました。CMP は、リモートインタフェースを経由したエンティティ Bean のインスタンスの状態表示だけを行い、Bean の関係は表示しませんでした。CMP の 1.1 バージョンでは、エンティティ Bean クラスのインスタンス変数を、データベースまたはリソースマネージャで状態を表すデータ項目にマッピングする必要があります。CMP インスタンスフィールドは配備記述子で指定されており、Bean を配備する際に、記述子はツールを使用してインスタンスフィールドのデータ項目へのマッピングを実装するコードを生成します。

Bean の実装クラスのコーディング方法も変更する必要があります。2.0 仕様に従って CMP を使用するエンティティ Bean 用の実装クラスは、抽象クラスとして定義されます。

持続性フィールドの定義

EJB 2.0 仕様では、エンティティ Bean のインスタンス変数を CMP フィールドまたは CMR フィールドとして指定できます。これらのフィールドは、配備記述子で定義します。CMP フィールドは、cmp-field 要素でマークされ、コンテナ管理による関係のフィールドは、cmr-field 要素でマークされます。

実装クラスでは、CMP および CMR フィールドを public 変数として宣言しないことに注意してください。代わりに、エンティティ Bean で get および set メソッドを定義して、これらの CMP および CMR フィールドの値を取得し、設定することができます。このような意味で、2.0 CMP を使用した Beans は、JavaBeans モデルに準拠しています。クライアントは、インスタンス変数に直接アクセスする代わりに、エンティティ Bean の get および set メソッドを使用してこれらのインスタンス変数を取得し、設定します。get および set メソッドは、CMP または CMR フィールドとして指定された変数にのみ関連しています。

エンティティ Bean の関係の定義

前述したとおり、EJB 1.1 アーキテクチャでは、エンティティ Beans 間の CMR をサポートしていません。EJB 2.0 アーキテクチャは、1 対 1、および 1 対多の CMR を両方ともサポートしています。関係は CMR フィールドを使用して表現されており、これらのフィールドは、配備記述子に関係としてマークされています。アプリケーションサーバーで適切な配備ツールを使用して、配備記述子に CMR フィールドを設定します。

CMP フィールドと同様、Bean はインスタンス変数として CMR フィールドを宣言しません。代わりに、Bean は、これらのフィールド用に get および set メソッドを備えています。

メッセージ駆動型 Beans

メッセージ駆動型 Beans は、EJB 2.0 アーキテクチャで導入されたもう一つの新しい機能です。メッセージ駆動型 Beans は、Java Message Service (JMS) 経由で配布された非同期メッセージを処理するトランザクション認識型のコンポーネントです。JMS API は、J2EE 1.3 プラットフォームの重要な部分です。

非同期メッセージングでは、アプリケーションはメッセージの交換によって通信することができるため、送信者と受信者を独立させることができます。送信者は、メッセージを送信した後に、受信者がそのメッセージを受信または処理するのを待つ必要はありません。これは、同期通信のプロセスとは異なります。同期通信では、別のコンポーネント上のメソッドを呼び出し、処理が完了して呼び出しコンポーネントに制御が戻るまで待機またはブロックするコンポーネントが必要です。

EJB クライアントアプリケーションの移行

この節には次の項目があります。

JNDI コンテキスト内での EJB の宣言

Sun ONE Application Server 7 では、EJB は JNDI のサブコンテキスト ejb/ に計画的にマッピングされています。JNDI 名 Account を EJB に所属させると、Sun ONE Application Server 7 は参照 ejb/Account をグローバル JNDI コンテキストに自動生成します。したがって、この EJB のクライアントは、対応するホームインタフェースを取得するために ejb/Account を検索する必要があります。

Sun ONE Application Server 6.0/6.5 に配備されているサーブレットメソッドのコードを見てみましょう。

ここに示すサーブレットは、JNDI コンテキストのルートにマッピングされているステートフルセッション Bean の BankTeller を呼び出します。ここに挙げるコードでは EJB のホームインタフェースを取得し、BankTeller オブジェクトのインスタンス化とこのオブジェクトのリモートインタフェース取得を可能にし、ビジネスメソッドからのこのコンポーネントの呼び出しを可能にします。

/**

   * Look up the BankTellerHome interface using JNDI.

   */

private BankTellerHome lookupBankTellerHome(Context ctx)

    throws NamingException

{

    try

    {

      Object home = (BankTellerHome) ctx.lookup("ejb/BankTeller");

      return (BankTellerHome) PortableRemoteObject.narrow(home, BankTellerHome.class);

    }

    catch (NamingException ne)

    {

     log("lookupBankTellerHome: unable to lookup BankTellerHome" +

        "with JNDI name 'BankTeller': " + ne.getMessage() );

     throw ne;

    }

}

このコードでは ejb/BankTeller を検索の引数としてすでに使用していますが、Sun ONE Application Server 7 に配備されるコードを変更する必要はありません。

EJB JNDI 参照の使用方法の要約

この節では、EJB JNDI 参照を使用した場合の注意事項をまとめて説明します。ここで説明する注意事項の詳細については、特定のソースアプリケーションサーバーのプラットフォームに固有のものであることに注意してください。

JNDI コンテキスト内の EJB 参照の配置

既存の WebLogic アプリケーションで JNDI コンテキストのルートに EJB がマップされている場合は、上述の JNDI コンテキスト内の EJB 参照の名前だけを変更する必要があります。変更によってこれらの参照が JNDI コンテキストルートからサブコンテキスト ejb/ に移動します。

これらの EJB が、既存のアプリケーションの JNDI サブコンテキスト ejb/ にすでにマップされている場合、変更の必要はありません。

ただし、重要なのは、Forte for Java の IDE 内の配備記述子に EJB の JNDI 名を設定する場合に、EJB の JNDI 名の中に接頭辞 ejb/ を含めないことです。これらの EJB 参照は、Sun ONE Application Server 7 では自動的に JNDI の ejb/ サブコンテキスト内に配備されることに留意してください。このため、EJB に、その配備記述子で BankTeller という JNDI 名が与えられた場合、この EJB への参照は Sun ONE Application Server によって ejb/BankTeller に「変換」されます。この EJB のクライアントコンポーネントは検索時にこの JNDI 名を使用することになります。

グローバル JNDI コンテキストとローカル JNDI コンテキスト

EJB 参照を取得するためにグローバル JNDI コンテキストを使用することは、Sun ONE Application Server 7 では完全に有効かつ最適なアプローチです。しかしながら、J2EE 仕様にできるだけ近い形で、EJB クライアントアプリケーションのローカル JNDI コンテキストを経由して EJB 参照を取得することをお勧めします。ローカル JNDI コンテキストを使用する場合、まずクライアント部分の配備記述子で EJB リソース参照を宣言する必要があります。これは Web アプリケーションでは web.xml、EJB コンポーネントでは ejb-jar.xml になります。

CMP エンティティ EJB の移行

この節では、アプリケーションコンポーネントを EJB 1.1 アーキテクチャから EJB 2.0 アーキテクチャに移行する手順について説明します。

CMP 1.1 の Bean を CMP 2.0 に移行するためには、まず特定の Bean が移行可能であることを確認する必要があります。確認の手順は次のとおりです。

  1. ejb-jar.xml ファイルから <cmp-field> 名へ移動し、オプションのタグ <prim-key-field>ejb-jar.xml 内にあり、指示された値を保持していることを確認します。問題がなければ、次の手順に進みます。
  2. ejb-jar.xml 内でフィールド名 <prim-key-class> を探し、クラス名を取得して、クラス内で宣言された public instance variablesを取得します。これらの変数のシグネチャ (名前と大文字小文字の区別) が上記の <cmp-field> 名と一致するかどうかを確認します。見つかったフィールドは分割します。これらの分割されたフィールドで、大文字で始まっているものがあるかどうかを調べます。もしある場合は、移行は実行できません。

  3. Bean クラスのソースコードを調べて、すべての <cmp-field> 変数の java 型を取得します。
  4. すべての <cmp-field> 名を小文字に変更し、それらの名前からアクセサを構築します。たとえば、元のフィールド名が Name で、その java 型が String である場合、アクセサメソッドシグネチャは次のようになります。
  5. Public void setName(String name)

       Public String getName()

  6. これらのアクセサメソッドシグネチャを、Bean クラスのメソッドシグネチャと比較します。正確に一致しない場合は、移行は実行されません。
  7. カスタム検索のメソッドシグネチャと、対応する SQL を取得します。SQL 内に Join 、 Outer join 、 OrderBy があるかどうかを確認します。ある場合は、移行は実行できません。これは、EJB QL では joins 、 Outer join 、および OrderBy をサポートしていないためです。
  8. CMP 1.1 検索が java.util.Enumeration を使用している場合は、代わりに java.util.Collection を使用する必要があります。これを反映するようにコードを修正してください。CMP2.0 検索では、java.util.Enumeration を返すことができません。

次の項目、「Bean クラスの移行」では移行プロセスを実行します。

Bean クラスの移行

この節では、Bean クラスの Sun ONE Application Server への移行に必要な手順について説明します。

  1. Bean クラス宣言の先頭にキーワード abstract を付けます。たとえば、Bean クラス宣言は次のようになります。
  2. Public class CabinBean implements EntityBean // before modification

    abstract Public class CabinBean implements EntityBean // after  modification

  3. アクセサの接頭辞にキーワード abstract を付けます。
  4. 変更後、Bean クラスのソースファイル、つまり拡張子 .java のファイルにすべてのアクセサをクラスレベルで挿入します。
  5. Bean クラスのソースファイル内で、すべての cmp フィールドをコメントにします。
  6. 小文字の cmp-field 名で protected インスタンス変数の宣言を構築し、クラスレベルでそれを挿入します。
  7. すべての ejbCreate() メソッド本体 (複数の ejbCreate が存在する場合もある) を読み込みます。パターン「<cmp-field>=値またはローカル変数」を検索し、「abstract ミューテータメソッド名 (値またはローカル変数)」に置き換えます。たとえば、移行前の ejbCreate の本体が次のとおりであるとします。
  8.       public MyPK ejbCreate(int id, String name)

                 {

              this.id = 10*id;

              Name = name;//1

              return null;

              }

    移行後、メソッド本体は変更され、次のようになります。

      public MyPK ejbCreate(int id, String name)

             {

          setId(10*id);

          setName(name);//1

          return null;

             }



//1 の abstract アクセサのメソッドシグネチャは、EJB 2.0 仕様で定められた Camel Case 規約に従っています。また、キーワード「this」は、元のソース内に存在する場合としない場合がありますが、変更後のソースファイルからは削除する必要があります。



  1. 手順 5 で ejbPostCreate() メソッドに宣言したすべての protected 変数を初期化する必要があります。protected 変数の数は、ejbCreate() メソッドの数と同じになります。初期化は、次のように初期化コードを挿入することにより行われます。
  2.       protected String name;//from step 5

          protected int id;//from step 5

          public void ejbPostCreate(int id, String name)

              {

    name /*protected variable*/ = getName();/*abstract accessor*/ //inserted in this step

    id /*protected variable*/ = getId();/*abstract accessor*/ //inserted in this step

              }

  3. ejbLoad メソッドの内部で、Beans のデータベースの状態に protected 変数を設定する必要があります。次のコードを挿入します。
  4.       public void ejbLoad()

              {

              name = getName();//inserted in this step

              id = getId(); //inserted in this step

                     ノノノ..      //already present code

              }

  5. 同様に、データベースの状態が更新されるように、ejbStore() 内部の Beans の状態を更新する必要があります。ただし、ejbCreate() の外部の主キーに対応するセッターは更新できないため、このメソッドの内部にはセッターを含めないでください。次のコードを挿入します。
  6.       public void ejbStore()

              {

              setName(name);//inserted in this step

          //  setId(id);//Do not insert this if it is a part of the primary key

                  ノノノノノノ..//already present code

              }

  7. Bean クラスソース、つまり拡張子 .java のファイルに対する最後の変更は、コード全体を調べ、すべての <cmp-field> 変数名を、手順 5 で宣言した対応する protected 変数名と置き換えることです。
  8. Bean を移行しない場合、少なくとも <cmp-version>1.x</cmp-version> タグを ejb-jar.xml 内部の適切な場所に挿入する必要があります。これで、移行しない Bean も Sun ONE Application Server 上で動作し続けます。

ejb-jar.xml の移行

ejb-jar.xml ファイルを Sun ONE Application Server に移行するには、次の手順を実行します。

  1. ejb-jar.xml で、すべての <cmp-field> を小文字に変更します。
  2. ejb-jar.xml ファイルで、<reentrant> タグの後に <abstract-schema-name> タグを挿入します。このスキーマ名は、<ejb-name> タグと同様、接頭辞 ias_ が付いた Bean 名になります。
  3. <primkey-field> タグの後に、次のタグを挿入します。
  4. <security-identity><use-caller-identity/></security-identity>

  5. SQL から EJB QL を構築するために、上記で取得した SQL を使用します。
  6. <query> タグ、およびネストされた子タグすべてを、すべての必要な情報とともに ejb-jar.xml に挿入します。挿入位置は <security-identity> タグのすぐ後です。

カスタム検索メソッド

カスタム検索メソッドは、エンティティ Bean のホームインタフェースで定義される findBy... メソッドです。デフォルトの findByPrimaryKey メソッドとは異なります。EJB 1.1 仕様は、これらの検索メソッドのロジックを定義する標準を定めていないため、EJB サーバーのベンダーは、実装を自由に選択できます。その結果、メソッドの定義に使用される手順は、ベンダーが選択する実装によって大幅に異なります。

Sun ONE Application Server 6.0 および 6.5 では、ファインダーロジックの指定に標準 SQL を使用します。

EJB の持続性記述子 Account-ias-cmp.xml に格納されるこの検索メソッドの定義に関する情報は、次のとおりです。

<bean-property>

  <property>

    <name>findOrderedAccountsForCustomerSQL</name>

    <type>java.lang.String</type>

    <value>

       SELECT BRANCH_CODE,ACC_NO FROM ACCOUNT where CUST_NO = ?

    </value>

    <delimiter>,</delimiter>

  </property>

</bean-property>

<bean-property>

  <property>

    <name>findOrderedAccountsForCustomerParms</name>

    <type>java.lang.Vector</type>

    <value>CustNo</value>

    <delimiter>,</delimiter>

  </property>

</bean-property>

このように、各 findXXX 検索メソッドには、配備記述子 (クエリ用 SQL コード、および関連パラメータ) 内に対応する 2 つのエントリがあります。

Sun ONE Application Server では、カスタム検索メソッドロジックも宣言型ですが、EJB のクエリ言語、EJB QL に基づいています。

EJB-QL 言語自体は使用できません。ejb-jar.xml ファイル内部の、<ejb-ql> タグで指定する必要があります。このタグは、<query> タグの内部にあり、EJB 内にクエリ (検索または選択メソッド) を定義します。EJB コンテナでは、各クエリを検索または選択メソッドの実装に変換できます。ここでは、<ejb-ql> タグの例を示します。

<ejb-jar>
  <enterprise-beans>
    <entity>
    <ejb-name>hotelEJB</ejb-name>
      ...
      <abstract-schema-name>TMBankSchemaName</abstract-schema-name>
      <cmp-field>...
      ...
      <query>
        <query-method>
          <method-name>findByCity</method-name>
          <method-params>
            <method-param>java.lang.String</method-param>
          </method-params>
        </query-method>
        <ejb-ql>
           <![CDATA[SELECT OBJECT(t) FROM TMBankSchemaName AS t WHERE t.city = ?1]]>
       
</ejb-ql>
      </query>
    </entity>
  ...
  </enterprise-beans>
...
</ejb-jar>


前へ      目次      索引      次へ     
Copyright 2002 Sun Microsystems, Inc. All rights reserved.