アプリケーション開発者は、Java™ Contexts and Dependency Injection (JCDI) を使用して、管理 Bean にさまざまなスコープを設定できます。例えば、
Foo という Java クラスに @javax.enterprise.context.ApplicationScoped アノテーションを指定し、
管理 Bean に @javac.inject.Inject アノテーションを付けた Foo フィールドが複数ある場合、実際に存在するアプリケーション・スコープの Foo インスタンスは 1 つしかありません。
このタスクについて
ライフサイクル・スコープは、アプリケーション開発者がコードを管理する際に役立ちます。
例えば、Java タイプに簡単なスコープ・アノテーションを
指定することにより、希望する動作を保証するために複数行のコードを作成しなくても、
そのスコープについて単一の管理対象インスタンスを作成することができます。
ライフサイクル・スコープは、管理 Bean にのみ適用されます。
アプリケーション・コードでクラスの新しいインスタンスが作成される場合は、
コードによって、その単一のインスタンスのライフサイクル全体が制御されます。
しかし、ランタイム環境がユーザーに代わって新しいインスタンスを作成する Java API for RESTful Web Services (JAX-RS) リソース・クラスなどの管理コードでは、
JAX-RS リソース環境が、ユーザーのクラスのライフサイクルの責任を持ちます。
ベスト・プラクティス: JCDI 対応のアーカイブでは、アプリケーションに存在する JAX-RS ルート・リソース
およびプロバイダー・クラスに特殊なライフサイクル・スコープを追加します。
@javax.ws.rs.Path アノテーション付き JAX-RS リソース・クラスの場合は、
@javax.enterprise.context.RequestScoped を使用できます。
javax.ws.rs.core.Application サブクラスおよび
@javax.ws.rs.ext.Provider アノテーション付きクラスの場合は、
@javax.enterprise.context.ApplicationScoped を使用する必要があります。
bprac
以下に、JCDI 対応の、JAX-RS を使用した簡単な Web アプリケーションでライフサイクル・スコープを使用する方法について説明します。
手順
- WEB-INF ディレクトリー内の Web アプリケーション (WAR) に beans.xml デプロイメント記述子を追加します。 WEB-INF/beans.xml ファイルがあるということは、
アーカイブが JCDI 対応のアーカイブであることを示しています。このタスクでは、
アーカイブに追加情報を追加する必要はありません。以下の例は、
基本的な WEB-INF/beans.xml ファイルを示しています。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/
XMLSchema-instance" xsi:schemeLocation="http://java.sun.com/xml/ns/javaee http:/
/java.sun.com/xml/ns/javaee/beans_1_0.xsd">
<!-- This is empty on purpose. -->
</beans>
- JAX-RS ルート・リソース・クラスを作成します。 以下の例は、簡単な JAX-RS ルート・リソース・クラスを示しています。
package com.example.jaxrs;
@javax.ws.rs.Path("exampleWithLifecycle")
public class StringResource {
@javax.ws.rs.GET
@javax.ws.rs.Produces(javax.ws.rs.core.MediaType.TEXT_PLAIN)
public String get() {
return "Hello world!";
}
}
- JCDI ライフサイクル・スコープを JAX-RS クラスに追加します。 @javax.enterprise.context.RequestScoped スコープ・アノテーションを
ルート・リソース・クラスに追加します。
ベスト・プラクティス: @javax.enterprise.context.RequestScoped アノテーションをルート・リソース・クラスに追加して、JAX-RS ルート・リソース・クラスが要求ごとに固有のインスタンスを持つようにします。
これは、非 JCDI 対応アプリケーションではデフォルトの動作です。
bprac
package com.example.jaxrs;
@javax.enterprise.context.RequestScoped
@javax.ws.rs.Path("exampleWithLifecycle")
public class StringResource {
@javax.ws.rs.GET
@javax.ws.rs.Produces(javax.ws.rs.core.MediaType.TEXT_PLAIN)
public String get() {
return "Hello world!";
}
}
- (オプション) カスタム @javax.ws.rs.ext.Provider アノテーション付きクラス
または javax.ws.rs.core.Application サブクラスの場合は、
クラスに @javax.enterprise.context.ApplicationScoped を追加する必要があります。 以下の例は、@javax.enterprise.context.ApplicationScoped スコープ・アノテーションを使用して JAX-RS プロバイダーまたはアプリケーション・サブクラスを変更する方法を示しています。
package com.example.jaxrs;
@javax.enterprise.context.ApplicationScoped
@javax.ws.rs.ext.Provider
public class Example implements javax.ws.rs.ext.MessageBodyWriter<CustomType> {
public long getSize(String t,
Class<?> type,
Type genericType,
Annotation[] annotations,
javax.ws.rs.core.MediaType mediaType) {
return -1;
}
public boolean isWriteable(Class<?> type,
Type genericType,
Annotation[] annotations,
javax.ws.rs.core.MediaType mediaType) {
return CustomType.class == type;
}
public void writeTo(String t,
Class<?> type,
Type genericType,
Annotation[] annotations,
javax.ws.rs.core.MediaType mediaType,
javax.ws.rs.core.MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException {
/* write something to the entity stream */
}
}
タスクの結果
JCDI を使用するように Web アプリケーションを構成し、
JCDI、ライフサイクル・スコープを使用した JAX-RS リソースおよびプロバイダーを作成しました。