Contexts and Dependency Injection および JSF 2.0 入門
執筆: Andy Gibson、管理: Troy Giunipero

JSR-299 で指定されている CDI (Contexts and Dependency Injection) は Java EE 6 の不可欠な部分であり、サーブレット、エンタープライズ Bean、および JavaBeans が、アプリケーションのライフサイクル内で明確なスコープを持って存在できるようにするためのアーキテクチャーを提供します。また、CDI サービスによって、EJB セッション Bean や JSF (JavaServer Faces) 管理対象 Bean などの Java EE コンポーネントが注入可能になり、イベントの起動や監視による疎結合方式の対話が可能になります。
このチュートリアルは、Andy Gibson 氏によって投稿された「JEE 6 での JSF 2.0 および CDI 入門」というタイトルのブログをベースにしています。ここでは、IDE を使用して、JSF 2.0 および CDI をサポートする Java Web プロジェクトを設定する方法を示します。そして CDI 管理対象 Bean を Facelets ページに接続する方法を示し、最後に EJB テクノロジとの CDI 統合の簡単な例を示します。
NetBeans IDE は、Contexts and Dependency Injection を組み込みでサポートしています (これには、プロジェクト作成時に beans.xml CDI 構成ファイルを生成するオプション、注釈のためのエディタおよびナビゲーションサポート、一般的に使用される CDI アーティファクトを作成するための各種ウィザードなどが含まれています)。
このチュートリアルを完了するには、次のソフトウェアとリソースが必要です。
注:
- NetBeans IDE の Java バンドル版には、Java EE 6 準拠のコンテナである GlassFish Server Open Source Edition 3.x も含まれています。
- CDI のサポートは、パッチ 1 を適用すれば NetBeans 6.8 でも使用できます。
CDI をサポートする Java Web プロジェクトの作成
この課題では、CDI をサポートする JSF 2.0 対応の Java Web プロジェクトを作成します。
- IDE のメインツールバーにある「新規プロジェクト」(
) ボタンをクリックします (Ctrl-Shift-N、Mac の場合は ⌘-Shift-N)。
- 「新規プロジェクト」ウィザードで、「Java Web」カテゴリを選択してから「Web アプリケーション」を選択します。「次へ」をクリックします。
- プロジェクト名として「
cdiDemo」と入力し、プロジェクトの場所を設定します。「次へ」をクリックします。
- サーバーを GlassFish 3.x に設定し、Java EE バージョンを Java EE 6 Web に設定します。「コンテキストと依存関係の注入を有効にする」オプションが選択されていることを確認します。
「コンテキストと依存関係の注入を有効にする」オプションが選択されると、プロジェクトテンプレートの作成時に、プロジェクトの WEB-INF フォルダに beans.xml ファイルが生成されます。beans.xml ファイルは CDI によって使用され、プロジェクトが CDI Bean を含むモジュールであることを Java EE 準拠のサーバーに伝えます。
- 「次へ」をクリックします。
- 「フレームワーク」パネルで「JavaServer Faces」オプションを選択します。
- 「構成」タブをクリックし、「優先ページ言語」として「Facelets」が選択されていることを確認します。「完了」をクリックします。
「完了」をクリックすると、IDE は Web アプリケーションプロジェクトを生成し、index.xhtml 開始ページがエディタに表示されます。
- 「プロジェクト」ウィンドウで「Web ページ」>「WEB-INF」フォルダノードを展開すると、
beans.xml ファイルが表示されます。現時点でこのファイルは空ですが、注釈の代わりとして、XML で Bean の関連情報を指定するために使用できます。
「ライブラリ」>「GlassFish Server」ノードを展開すると、weld-osgi-bundle.jar ライブラリが自動的に追加されていることがわかります。GlassFish サーバーには、JSR-299 CDI 仕様の JBoss の実装である Weld が含まれています。
JSF の式言語からの Bean へのアクセス
この課題では、EL 構文を使用して CDI 管理対象 Bean を Facelets ページに接続する方法を示します。
- 「プロジェクト」ウィンドウで「ソースパッケージ」ノードを右クリックし、「新規」>「Java クラス」を選択します。
- 「新規 Java クラス」ウィザードで、「クラス名」に「MessageServerBean」、「パッケージ」に「exercise1」と入力します (ウィザードの完了時に新しいパッケージが作成されます)。

- 「完了」をクリックします。新しいパッケージおよびクラスが生成され、エディタでクラスが開きます。
javax.inject.Named 注釈でクラスに注釈を付けて、文字列を返す単一のメソッドを作成します。
package exercise1;
import javax.inject.Named;
@Named
public class MessageServerBean {
public String getMessage() {
return "Hello World!";
}
}
@Named 注釈の入力中に Ctrl- スペースキーを押すと、エディタのコード補完サポートと Javadoc ドキュメントを呼び出せます。エディタのコード補完機能を使用して注釈を適用する (適切な注釈を選んで Enter を押す) と、自動的に import 文がファイルに追加されます。
Javadoc のポップアップで「外部 Web ブラウザにドキュメントを表示」(
) ボタンをクリックすると、別個のウィンドウにフルサイズの Javadoc を表示することもできます。
- ファイルを保存します (Ctrl-S、Mac の場合は ⌘-S)。
@Named 注釈を追加することで、CDI で定義されているように MessageServerBean クラスは管理対象 Bean になります。
- エディタで (Ctrl-Tab キーを押して)
index.xhtml Facelets ページに切り替え、<h:body> タグに次の内容を追加します。
<h:body>
Hello from Facelets
<br/>
Message is: #{messageServerBean.message}
<br/>
Message Server Bean is: #{messageServerBean}
</h:body>
EL 式で Ctrl- スペースキーを押すと、コード補完の候補を利用できます。エディタのコード補完によって、管理対象 Bean およびそのプロパティーが一覧表示されます。MessageServerBean クラスは @Named 注釈によって CDI 管理対象 Bean に変換されるため、JSF 管理対象 Bean と同じように EL 構文内でアクセスできるようになります。

- IDE のメインツールバーにある「プロジェクトを実行」(
) ボタンをクリックします。プロジェクトがコンパイルされて GlassFish に配備され、アプリケーションの開始ページ (index.xhtml) がブラウザで開きます。「Hello World!」メッセージが MessageServerBean によってページに表示されます。

- メッセージ Bean に戻って、メッセージを何かほかのもの (「Hello Weld!」など) に変更します。ファイルを保存 (Ctrl-S、Mac の場合は ⌘-S) してからブラウザを更新します。新しいメッセージが自動的に表示されます。IDE の「保存時に配備」機能によって、保存した変更はすべて自動的にコンパイルされてサーバーに再配備されます。
ページの 3 行目から、クラス名が exercise1.MessageServerBean であることが確認できます。この Bean は単なる POJO (Plain Old Java Object) であることに注目してください。Java EE で開発しているにもかかわらず、トランザクションやインターセプタなどが何層にも重なった複雑なクラス階層は必要ありません。
仕組み
アプリケーションが配備されるとき、beans.xml ファイルの存在によってモジュールに CDI 管理対象 Bean が含まれていることが示されるため、パス上のクラスに対して CDI 注釈のスキャンが行われます。CDI モジュールでは、すべての Bean は Weld に登録され、@Named 注釈を使用して Bean が注入ポイントと照合されます。index.xhtml ページが描画されたとき、JSF は、JSF に登録された式リゾルバを使用してページの messageServerBean の値を解決しようとしました。このうちの 1 つが、messageServerBean という名前で登録された MessageServerBean クラスを持つ Weld EL リゾルバです。@Named 注釈で別の名前を指定することもできましたが、指定しなかったため、クラス名の最初の文字を小文字にしたデフォルト名で登録されました。Weld リゾルバは、JSF からの要求に応じてこの Bean のインスタンスを返します。EL 式を使用する場合にのみ Bean を命名する必要があります。CDI ではクラスの型と限定子注釈を使用することで、型を保証して注入できるため、注入の機構として Bean の命名を使用しないでください。
EJB へのアップグレード
Java EE のスタックを使用しているため、EJB 3.1 のおかげで少し変更を加えるだけで Bean を EJB として簡単に配備できます。
MessageServerBean を開き、クラスレベルで javax.ejb.Stateless 注釈を追加して、文字列を「Hello EJB!」に変更します。
package exercise1;
import javax.ejb.Stateless;
import javax.inject.Named;
/**
*
* @author nbuser
*/
@Named
@Stateless
public class MessageServerBean {
public String getMessage() {
return "Hello EJB!";
}
}
- ファイルを保存 (Ctrl-S、Mac の場合は ⌘-S) してからブラウザに移動して再表示します。次のような出力が表示されます。
驚くことに、ただ 1 つの注釈で POJO が各種機能を備えた EJB に変わりました。変更を保存してからページを更新すると、変更した内容が表示されました。これを行うために、独特のプロジェクト構成、ローカルインタフェース、または難解な配備記述子は一切必要ありませんでした。
異なる EJB の種類
@Stateful 注釈を使用することもできます。または、シングルトンインスタンスのための新しい @Singleton 注釈を試すこともできます。そうすると、javax.ejb.Singleton と javax.inject.Singleton の 2 つの注釈があることに気付くでしょう。なぜシングルトンが 2 つあるのでしょうか。EJB 以外の環境で CDI を使用している場合、CDI のシングルトン (javax.inject.Singleton) を使用して EJB の外部でシングルトンインスタンスを定義できます。EJB のシングルトン (javax.ejb.Singleton) は、トランザクション管理などの EJB の機能をすべて提供します。つまり、必要に応じて、または EJB 作業環境の有無に応じて選択できるようになっています。
関連項目
このシリーズの次回では CDI 注入に焦点をあて、Java EE 6 環境での依存関係の管理のために CDI を使用する方法について詳しく見ていきます。
CDI および JSF 2.0 の詳細については、次のリソースを参照してください。
Contexts and Dependency Injection
JavaServer Faces 2.0