Java EE 7 CDIを使う際の注意点──『Java EE 7徹底入門』番外編 第2回

Oracle Java & Developers編集部
2016-03-23 11:00:00
  • このエントリーをはてなブックマークに追加

Java EE 7のビジネスロジック開発技術であるCDI(Contexts and Dependency Injection)を使う際には、いくつか注意すべきポイントがある。『Java EE 7徹底入門』の著者が解説する。


Java EE 7徹底入門(発行:翔泳社)

 本企画では、日本Javaユーザーグループ(JJUG)が2016年2月に開催した「JJUGナイトセミナー ─『Java EE 7徹底入門』の著者が解説!-Java EE 7特集」の内容を基に、『Java EE 7徹底入門 標準Javaフレームワークによる高信頼性Webシステムの構築』(翔泳社刊)の著者として同セミナーで講師を務めた日本オラクルのスペシャリストらによるJava EE 7の初級者向け解説をお届けしている。前回は「Java EE 7の概要」と「プレゼンテーション層の開発」を取り上げたが、続く今回は、日本オラクル クラウド・テクノロジーコンサルティング統括本部の羽生田恒永氏が、Java EE 7におけるビジネスロジック層の開発技術であるCDIを使う際の注意点について解説する。

必要なときに必要なオブジェクトを呼び出せる、簡単で便利なCDI


日本オラクル クラウド・テクノロジーコンサルティング統括本部の羽生田恒永氏

 『Java EE 7徹底入門』では5~6章でCDIとEJBによるビジネスロジックの開発について解説していますが、刊行後に1つご指摘をいただいたことがあるので、初めにそれについて触れておきたいと思います。

CDIとEJBは"排他ではない"

 『Java EE 7徹底入門』では、主に5章で「CDIの利用」、6章で「EJBの利用」について解説しています。その中で「CDI or EJB」や「選択」といった表現を使いましたが、これにより、読者の皆さんにCDIとEJBは排他的な関係にあるという印象を抱かせてしまったかもしれません。

  実際にコンサルティングの現場でも、お客様から「CDIとEJBはどちらを使えばよいのか」といった質問をされることがありますが、両者は決して排他的な関係にはありません。現実的には、両者を組み合わせて課題を解決するのが善作だと考えています。本書に記載されている内容に、この点について一部誤解を生じさせるような記載があったようですので、それについてお詫びいたします。

 さて、以降ではCDIの基本を説明していきますが、特に『Java EE 7徹底入門』に書かなかったこと/書けなかったことを中心に取り上げていきたいと思います。

スコープ定義を覚えることがCDI活用の第一歩

 まずCDIについて簡単におさらいしておきましょう。CDIとは「Contexts and Dependency Injection」の略称です。Dependency Injection(DI)とは、アプリケーションを構成する複数の"層"をつなげる役割を果たす技術であり、初めにインタフェースを定義し、そのインタフェース間でのオブジェクトのやり取りを実装するというかたちで使います。

 CDIの特徴は、アプリケーションの動作に必要となるオブジェクトを、必要となったタイミングで取得するための仕組みを備えている点であり、そのために「スコープ定義」を使います。スコープの中にあるオブジェクトをどのように扱うかが、CDIを使ううえでの重要なポイントになります。

 それでは、「スコープ定義」とは、どのようなものでしょうか。スコープ定義を書くと、「@Inject」というアノテーションを使い、プログラム内の任意の個所でインジェクション(Injection。オブジェクトの注入)が行えるようになります。主なスコープには「@RequestScoped」、「@ViewScoped」、「@SessionScoped」、「@ApplicationScoped」、「@ConversationScoped」の5つがあります。これらのスコープの定義をきちんと覚え、各スコープにおけるオブジェクトのライフサイクルを意識すれば、CDIの基本機能が使えます。

 CDIの使い方を図示すると、下図のようになります。

 ご覧のとおり、サーブレットなどのプログラムで、変数名の部分に「@Inject」というアノテーションを付けておきます。そして、CDIによって呼び出されるJavaクラス(CDIビーン)の側では、そのクラスをインジェクションできるスコープを定義します。すると、サーブレットが呼び出された際、定義したスコープでCDIビーンのインスタンスが生成/代入されて使えるようになります。

CDIとEJBの違い

 このように、CDIは非常に簡単で便利な仕組みであり、極論すればスコープ定義さえ覚えれば使うことができます。

 また、EJBコンポーネントの場合、呼び出しと同時に必ずトランザクションが立ち上がりますが、CDIでは不要であればトランザクションを使わなくてもよいため、リソース面のメリットが期待できます。

 さらに、EJBを使う場合、通常はアプリケーション・サーバ側でEJB用のリソース・プールが確保されます。キャッシュとして存在するため適切にチューニングするのが難しいのですが、CDIではスコープが細かく分かれているので、必要なときに必要な数だけオブジェクトを使い、終わったらすぐに解放するといったことができます。「使いたい場面で使い、使い終わったらすぐに片付ける」というのが、CDIを使う場合の理想的なかたちです。

CDIがつなぐ3つの層

 先ほど、CDIはアプリケーションで複数の"層"をつなぐものだと説明しました。この層には何があるのかというと、下図に示すように「プレゼンテーション層」、「業務ロジック層」、「永続化層」の3つがあります。

 プレゼンテーション層とは、第1回で取り上げたJSFなどで作る層です。

 また、業務ロジック層とは、ビジネスロジックを定義する層です。CDIはビジネスロジックの作成に使えるため、上の図ではこの層の上にCDIを配置しています。ただし、実際には各層をつなぐ役割を果たすので、他の層にも関係します。CDIの役割は非常に幅広いため、実際にアプリケーションを作ってみたら下図のような構成になったということもよくあります。

 こうなると、アプリケーションの大半がCDIによって作られることになります。CDIは、もともと各層の"接着剤"として利用することが前提にあるため、このような適用範囲の広い使われ方が想定されます。開発の際には、どの層で利用するオブジェクトなのか、どこで参照が切れるのかを意識し、スコープ定義をうまく制御することが求められるでしょう。