EJB および CDI との JAX-RS 2.0 の統合
Java™ API for RESTful Web Services (JAX-RS) 2.0 は、 WebSphere® Application Server traditional V9で Enterprise JavaBeans (EJB) および Contexts and Dependency Injection (CDI) と統合します。
JAX-RS 2.0 がエンタープライズ Bean とともに機能するためには、
@Path
を使用して Bean のクラスにアノテーションを付け、それをルート・リソース・クラスに変換する必要があります。
EJB との統合により、EJB Bean にアノテーションを付けてそれらを REST エンドポイントとして示すことができます。 また、Java Transaction API (JTA) および EJB のセキュリティー機能を使用することもできます。 WebSphere Application Server traditional の JAX-RS 2.0 は、ルート・リソース・クラス、プロバイダー、およびアプリケーション・サブクラスとしてのステートレスおよび singleton セッション Bean の使用をサポートします。
CDI との統合により、 CDI Bean または Managed Bean に REST エンドポイントとしてアノテーションを付けることができ、 Web サービス用に CDI 注入を使用できます。 WebSphere Application Server traditional の JAX-RS 2.0 は、ルート・リソース・クラス、プロバイダー、およびアプリケーション・サブクラスとして CDI スタイルの Bean をサポートします。 プロバイダーおよびアプリケーション・サブクラスはシングルトンでなければならないか、 または、アプリケーション・スコープを使用する必要があります。 CDI 仕様により、さまざまなタイプの Java EE コンポーネントの統合が容易になります。 これは、EJB や Managed Bean などのコンポーネントを Java Server Pages (JSP) や他の EJB といった他のコンポーネントに注入するための共通メカニズムを提供します。
- ステートレス・セッション Bean の場合、以下の例に示されているように
@Stateless
アノテーションを使用します。@Stateless @Path("stateless-bean") public class StatelessResource {...}
- シングルトン Bean の場合、以下の例に示されているように
@Singleton
アノテーションを使用します。@Singleton @Path("singleton-bean") public class SingletonResource {...}
@ApplicationScoped
アノテーションと @Inject
アノテーションをアプリケーション・スコープの Bean で使用できます。@ApplicationScoped
@Path("/ApplicationScopedResource")
public class ApplicationScopedResource {
private @Inject
SimpleBean injected;
...
}
EJB および CDI とともに JAX-RS 2.0 を使用する場合の制約事項
WebSphere Application Server traditionalの JAX-RS 2.0 の制約事項については、以下の項目を参照してください。
- JAX-RS リソース、プロバイダー、またはアプリケーションとして EJB を使用する場合、
EJB Bean のコンストラクターで
@Context
注入を使用することはできません。注: このケースの理由は、デフォルト・コンストラクターを持つ EJB は、EJB および JAX-RS 仕様に基づく JAX-RS にのみ使用できるためです。 - Application クラスは、インターフェースを実装していないか、または
@Localbean
アノテーションを持っている場合、EJB と見なされます。 しかし、ローカル・インターフェースまたは POJO インターフェースを実装している場合は、EJB とは見なされません。 - プロバイダーについて、クラスが有効な EJB プロバイダーと見なされるか否かの条件を次にリストします。
- クラスが
@Local
アノテーションなしで POJO プロバイダー・インターフェースのみを実装する場合、それは有効な EJB プロバイダーと見なされます。 - クラスが
@LocalBean
アノテーションを含み、POJO プロバイダー・インターフェースを実装する場合、それは有効な EJB プロバイダーと見なされます。 - クラスが
@Local
アノテーション付きのローカル・インターフェースを含んでいる場合、そのローカル・インターフェースはプロバイダー・インターフェースです。 このクラスがプロバイダー・インターフェースを実装する場合、それは有効な EJB プロバイダーです。 - クラスが
@Local
アノテーション付きのローカル・インターフェースを含んでいて、 そのローカル・インターフェースがプロバイダー・インターフェースではない場合、それは有効なプロバイダーではありません。 この場合、EJB コンテナーは POJO プロバイダー・インターフェースではなく、ローカル・インターフェースの EJB スタブしか生成できないからです。 - クラスが
@Local
アノテーションを持っているが、そのアノテーションがクラスの参照するプロバイダー・インターフェースを実装しない場合は、クラスは有効なプロバイダーではありません。 JAX-RS 2.0 仕様によると、プロバイダーとは、この仕様で導入された 1 つ以上の JAX-RS インターフェースを実装していて、自動ディスカバリーのために@Provider
でアノテーションを付けることのできるクラスです。
- クラスが
- リソースについて、クラス内のメソッドを JAX-RS リソースとして使用できるか否かの条件を次にリストします。
- EJB ベースのリソースがインターフェースを何も実装しない場合、このクラスで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。
- EJB ベースのリソースが 1 つのインターフェース (ローカルまたは POJO) を実装する場合、このインターフェースで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。
- EJB ベースのリソースが複数のインターフェースを実装する場合は、次のようになります。
- すべてのインターフェースが
@Local
アノテーションなしの POJO インターフェースである場合、インターフェースで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。 - すべてのインターフェースが
@Local
アノテーション付きのローカル・インターフェースである場合、インターフェースで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。 - 一部のインターフェースが
@Local
アノテーション付きのローカル・インターフェースであり、その他のインターフェースがローカル・インターフェースではない場合、ローカル・インターフェースで宣言されているメソッドのみが JAX-RS リソースとして使用可能です。注: このケースの理由は、EJB コンテナーがローカル・インターフェース用の EJB スタブを生成できるのは、このシナリオの場合のみであるためです。 - EJB ベースのリソースに
@LocalBean
アノテーションが付いている場合、クラスで宣言されているすべてのメソッドが JAX-RS リソースとして使用可能です。 - 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 2.0 | EJB | 結果 |
---|---|---|---|
リソース | perRequest | ステートレス | ステートレス |
perRequest | Singleton | Singleton | |
Singleton | ステートレス | ステートレス | |
Singleton | Singleton | Singleton | |
Provider | Singleton | ステートレス | ステートレス |
Singleton | Singleton | Singleton |
JAX-RS 2.0 スコープと CDI スコープのライフサイクル
アプリケーション | JAX-RS 2.0 スコープ | CDI スコープ・アノテーション | 結果 |
---|---|---|---|
リソース | perRequest | @ApplicationScoped | Singleton |
perRequest | @RequestScoped | perRequest | |
perRequest | @Dependent | perRequest | |
perRequest | @SessionScoped | セッション | |
perRequest | perRequest | ||
Singleton | @ApplicationScoped | Singleton | |
Singleton | @RequestScoped | perRequest | |
Singleton | @Dependent | Singleton | |
Singleton | @SessionScoped | セッション | |
Singleton | Singleton | ||
Provider | Singleton | @ApplicationScoped | Singleton |
Singleton | @RequestScoped | Singleton | |
Singleton | @Dependent | Singleton | |
Singleton | @SessionScoped | Singleton | |
Singleton | Singleton |
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}.)。 WebSphere Application Server traditional はリソース・インスタンスを {3} から取得します。(WebSphere Application Server traditional gets resource instance from {3}.)
このメッセージは、 JAXRS-2.0 リソース・スコープが CDI スコープと一致せず、リソース・インスタンスが CDI に存在するため、 WebSphere Application Server traditional がリソース・インスタンスを CDI から取得する場合に表示されます。 インスタンスは、JAXRS から取得される場合は CDI 注入を含みません。CWWKW1002W: JAXRS-2.0 プロバイダー {0} の CDI スコープは {1} です (The CDI scope of JAXRS-2.0 Provider {0} is {1}.)。 WebSphere Application Server traditional はプロバイダー・インスタンスを {2} から取得します。(WebSphere Application Server traditional gets the provider instance from {2}.)
このメッセージが表示される理由は、プロバイダー・インスタンスがシングルトンのみであることです。 WebSphere Application Server traditional は、プロバイダーの CDI スコープが Dependent または ApplicationScopedの場合、プロバイダー・インスタンスを CDI から取得します。 インスタンスは、JAXRS から取得される場合は CDI 注入を含みません。