EJB および CDI との JAX-RS 2.0 の統合

Liberty における JAX-RS 2.0 は Enterprise JavaBeans (EJB) および Contexts and Dependency Injection (CDI) と統合します。

JAX-RS 2.0 がエンタープライズ Bean とともに機能するためには、 @Path を使用して Bean のクラスにアノテーションを付け、それをルート・リソース・クラスに変換する必要があります。

EJB との統合により、EJB Bean にアノテーションを付けてそれらを REST エンドポイントとして公開することができます。また、JTA や、EJB のセキュリティー機能を使用することもできます。Liberty における JAX-RS 2.0 は、 ルート・リソース・クラス、プロバイダー、およびアプリケーション・サブクラスとして、 ステートレス・セッション Bean およびシングルトン・セッション Bean を使用することをサポートします。CDI との統合により、 CDI Bean または Managed Bean に REST エンドポイントとしてアノテーションを付けることができ、 Web サービス用に CDI 注入を使用できます。Liberty における JAX-RS 2.0 は、ルート・リソース・クラス、 プロバイダー、およびアプリケーション・サブクラスとして、CDI スタイルの Bean をサポートします。プロバイダーおよびアプリケーション・サブクラスはシングルトンでなければならないか、 または、アプリケーション・スコープを使用する必要があります。CDI 仕様は、 さまざまなタイプの Java™ EE コンポーネントの統合を簡単にします。また、これによって、EJB や Managed Bean などのコンポーネントを JSP または他の EJB といった別のコンポーネントに注入する一般的なメカニズムが提供されます。

EJB の場合、ステートレス・セッション Bean およびシングルトン POJO Bean でアノテーションを使用できます。
  • ステートレス・セッション Bean の場合、以下の例に示されているように @Stateless アノテーションを使用します。
    @Stateless
    @Path("stateless-bean")
    public class StatelessResource {...}
  • シングルトン Bean の場合、以下の例に示されているように @Singleton アノテーションを使用します。
    @Singleton
    @Path("singleton-bean")
    public class SingletonResource {...}
CDI の場合、@ApplicationScoped アノテーションと @Inject アノテーションをアプリケーション・スコープの Bean で使用できます。
ヒント: CDI フィーチャーが使用不可になっている場合、JAX-RS はエラーを報告しませんが、インスタンスは POJO を使用して取得されます。
@ApplicationScoped
@Path("/ApplicationScopedResource")
public class ApplicationScopedResource {

    private @Inject
    SimpleBean injected;

...

}

EJB および CDI とともに JAX-RS 2.0 を使用する場合の制約事項

Liberty における JAX-RS 2.0 の制約事項については、以下の項目を参照してください。

  • JAX-RS リソース、プロバイダー、またはアプリケーションとして EJB を使用する場合、 EJB Bean のコンストラクターで @Context 注入を使用することはできません。その理由は、EJB および JAX-RS の仕様によると、JAX-RS に使用できるのは、 デフォルトのコンストラクターのみであるためです。
  • EJB または CDI アノテーションを Java クラス内で使用しているが、 EJB 用の Liberty フィーチャー (ejbLite-3.2 など) または CDI 用の Liberty フィーチャー (cdi-1.0 など) が server.xml ファイルに構成されていない (これは、Liberty ランタイムで EJB または CDI のサポートがないことを意味します) 場合、 JAX-RS 2.0 エンジンはその Java クラスを POJO クラスとして使用します。
  • Application クラスは、インターフェースを実装していないか、 または @Localbean アノテーションがある場合、EJB と見なされ、 ローカル・インターフェースまたは POJO インターフェースを実装している場合は EJB とは見なされません。
    • プロバイダーの場合:
      • クラスが @Local アノテーションなしで POJO プロバイダー・インターフェースのみを実装する場合、それは有効な EJB プロバイダーと見なされます。
      • クラスが @LocalBean アノテーションを含み、POJO プロバイダー・インターフェースを実装する場合、それは有効な EJB プロバイダーと見なされます。
      • クラスが @Local アノテーション付きのローカル・インターフェースを含んでいる場合、そのローカル・インターフェースはプロバイダー・インターフェースです。このクラスがプロバイダー・インターフェースを実装する場合、それは有効な EJB プロバイダーです。
      • クラスが @Local アノテーション付きのローカル・インターフェースを含んでいて、 そのローカル・インターフェースがプロバイダー・インターフェースではない場合、それは有効なプロバイダーではありません。

        その理由は、このようなケースでは、 EJB コンテナーは、POJO プロバイダー・インターフェースではなく、ローカル・インターフェースについてのみ、EJB スタブを生成できるためです。

      • クラスが、プロバイダー・インターフェースを参照する @Local アノテーションを含んでいるだけで、このプロバイダー・インターフェースを実装していない場合、 JAX-RS 2.0 仕様によると、それは有効なプロバイダーではありません。 プロバイダーとは、この仕様で導入された 1 つ以上の JAX-RS インターフェースを実装していて、 自動ディスカバリーのために @Provider でアノテーションを付けることのできるクラスです。
    • リソースの場合:
      • EJB ベースのリソースがインターフェースを何も実装しない場合、このクラスで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。
      • EJB ベースのリソースが 1 つのインターフェース (ローカルまたは POJO) を実装する場合、このインターフェースで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。
      • EJB ベースのリソースが複数のインターフェースを実装する場合は、次のようになります。
        1. すべてのインターフェースが @Local アノテーションなしの POJO インターフェースである場合、インターフェースで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。
        2. すべてのインターフェースが @Local アノテーション付きのローカル・インターフェースである場合、インターフェースで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。
        3. 一部のインターフェースが @Local アノテーション付きのローカル・インターフェースであり、その他のインターフェースがローカル・インターフェースではない場合、 ローカル・インターフェースで宣言されているメソッドのみが JAX-RS リソースとして使用可能です。その理由は、このシナリオでは、EJB コンテナーはローカル・インターフェースにのみ EJB スタブを生成できるためです。
        4. EJB ベースのリソースに @LocalBean アノテーションが付いている場合、クラスで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。
        5. EJB ベースのリソースがインターフェースを実装する場合、 そのインターフェースで JAX-RS リソース・メソッドが宣言される必要があります。そのインターフェースが、変更できないプロバイダーである場合、 リソース・クラス用の新しいインターフェースを作成して、リソース・メソッドを追加する必要があります。それ以外の場合は、 EJB リソースと見なされません。
  • @Path アノテーション付きのリソース・クラスが JAX-RS プロバイダー・インターフェースを実装しているか、@Provider アノテーションで宣言している場合、 このクラスはリソースとプロバイダーの両方として機能します。この場合、デフォルトで、JAX-RS 2.0 エンジンは、 このクラスの 1 つのみのインスタンスを使用し、それがリソースとプロバイダーで共有されます。 このインスタンスのライフサイクルはシングルトンです。
  • クラスが、アプリケーション・クラスの getClasses メソッドと getSingletons メソッドの両方に登録されている場合、 デフォルトで、JAX-RS 2.0 エンジンは、getSingletons メソッドからのインスタンスを使用し、getClasses メソッド内の登録を無視します。
  • RESTful リソースが CDI Managed Bean でもあり、そのスコープが javax.enterprise.context.Dependent である場合、CDI 制約事項のため、PreDestroy メソッドを呼び出すことができません。

JAX-RS 2.0 Bean と EJB Bean のライフサイクル

JAX-RS Bean と EJB Bean のライフサイクルは異なります。JAX-RS と EJB の Bean ライフサイクルが競合する場合、 ライフサイクルは Liberty の EJB コンテナーによって管理されます。したがって、JAX-RS ライフサイクルが機能しない間は EJB インスタンスが適用されます。詳しくは、次の表を参照してください。
表 1. JAX-RS 2.0 Bean と EJB Bean のライフサイクル
アプリケーション JAX-RS 2.0 EJB 結果
リソース perRequest ステートレス ステートレス
  perRequest シングルトン シングルトン
  シングルトン ステートレス ステートレス
  シングルトン シングルトン シングルトン
プロバイダー シングルトン ステートレス ステートレス
  シングルトン シングルトン シングルトン

JAX-RS 2.0 スコープと CDI スコープのライフサイクル

Bean にはスコープがあり、Bean のインスタンスのライフサイクルはスコープによって決まります。JAX-RS と CDI では、スコープは少し異なります。JAX-RS と CDI のスコープ・ライフサイクルが競合する場合、結果は次の表のようになります。
表 2. JAX-RS 2.0 スコープと CDI スコープのライフサイクル
アプリケーション JAX-RS 2.0 スコープ CDI スコープ・アノテーション 結果
リソース perRequest @ApplicationScoped シングルトン
  perRequest @RequestScoped perRequest
  perRequest @Dependent perRequest
  perRequest @SessionScoped Session
  perRequest   perRequest
  シングルトン @ApplicationScoped シングルトン
  シングルトン @RequestScoped perRequest
  シングルトン @Dependent シングルトン
  シングルトン @SessionScoped Session
  シングルトン   シングルトン
プロバイダー シングルトン @ApplicationScoped シングルトン
  シングルトン @RequestScoped シングルトン
  シングルトン @Dependent シングルトン
  シングルトン @SessionScoped シングルトン
  シングルトン   シングルトン

JAX-RS 2.0 スコープと CDI スコープのライフサイクル競合メッセージ

JAX-RS 2.0 と CDI のスコープのライフサイクルが競合する場合、以下の警告メッセージが表示されます。これらは警告メッセージであり、アクションは不要です。

  • CWWKW1001W: JAXRS-2.0 リソース {0} のスコープ {1} は CDI スコープ {2} と一致していません (The scope {1} of JAXRS-2.0 Resource {0} does not match the CDI scope {2}.)。Liberty はリソース・インスタンスを {3} から取得します (Liberty gets resource instance from {3}.)。
    このメッセージは、 JAXRS-2.0 リソースのスコープが CDI スコープと一致せず、リソース・インスタンスが CDI に存在し、 その結果として Liberty がリソース・インスタンスを CDI から取得する場合に表示されます。インスタンスは、JAXRS から取得される場合は CDI 注入を含みません。
  • CWWKW1002W: JAXRS-2.0 プロバイダー {0} の CDI スコープは {1} です (The CDI scope of JAXRS-2.0 Provider {0} is {1}.)。Liberty はプロバイダー・インスタンスを {2} から取得します (Liberty gets the provider instance from {2}.)。
    このメッセージが表示される理由は、プロバイダー・インスタンスがシングルトンのみであることです。Libertyは、 プロバイダーの CDI スコープが Dependent または ApplicationScoped の場合、プロバイダー・インスタンスを CDI から取得します。インスタンスは、JAXRS から取得される場合は CDI 注入を含みません。

トピックのタイプを示すアイコン 参照トピック



タイム・スタンプ・アイコン 最終更新: Tuesday, 6 December 2016
http://www14.software.ibm.com/webapp/wsbroker/redirect?version=cord&product=was-nd-mp&topic=rwlp_jaxrs2.0_ejbcdi
ファイル名: rwlp_jaxrs2.0_ejbcdi.html