読者です 読者をやめる 読者になる 読者になる

見習いプログラミング日記

Java EE を中心に色々なことを考えてみます。目指せ本物のプログラマ。

JavaEE7の"Managed Bean"の行方

JavaEE6を使い始めて、つまずいたのが"Managed Bean"の考え方。

JavaEE6では、大きく分けて以下のコンテナ管理Beanがある。

  • JSFのManagedBean
  • CDIのManagedBean
  • EJBのManagedBean
  • Servlet、Filter、JAX-RSJPAなどのその他コンテナ管理オブジェクト
  • @javax.annotation.ManagedBeanでアノテートされたクラス

それぞれどんなコンセプトがあって、JavaEE7に向けてどう整理していくのか。
JavaEE7仕様策定エキスパートグループのメーリングリストでも議論されている。

以下、不正確な点も多いと思うが、JavaEEのSpecLeadの提案を翻訳してみた。
原文と、本文中に出てくるMatrix(表資料)のURLはこちら。
http://java.net/projects/javaee-spec/lists/jsr342-experts/archive/2012-03/message/74


[jsr342-experts] 管理Beanの整理

JavaEE6の中で競合問題が発生しているJavaEECDIの管理Beanの扱いについて、より良い方法を整理していきたいと思います。

コミュニティの間では、JavaEEの管理Beanとは何か、JavaEE管理BeanとCDIをどうやって関連づけるのか混乱が生じています。

JavaEE6では、JavaEE管理オブジェクトに適用される機能の範囲を定義するためにManagedBean仕様が制定されました。
基本的な管理Beanはコンテナ管理オブジェクトであり、最小限の基礎的なサービス、例えばリソースインジェクションや、ライフサイクルコールバック、インターセプタ、JNDIからルックアップであったりインジェクションなどをサポートしています。

基本的な管理Beanモデルは変更が許されており、ManagedBean仕様に含まれる以下の内容から変更可能であることを読み取ることができます。

  • 管理Beanの定義
  • 管理Beanの生成方法の定義
  • 管理Beanの命名規則
  • ライフサイクルモデル
  • java:compのネームスペースを持つこと
  • スレッド要件
  • インターセプタ機構

この方法による管理Beanの定義で、私たちはコンポーネントモデルのもとで進化する汎用機能のカバー範囲を整理しました。

CDI管理Beanもまた、最小限の定義がされています。要件は引数なしコンストラクタを持つことと、コンストラクタは@Injectでアノテートされることのみです。(詳細な定義はCDI仕様3.1.1参照)

しかしながら、CDI管理Beanの定義はごくわずかです。
(引数なしコンストラクタを持つクラスはCDI管理Beanになれる)
多くのJavaEE管理クラス、特にJavaEE仕様書のTable EE5-1("Component classes supporting injection")に定義されているものはCDI管理Beanとして扱うことも可能です。
今日ではしかしながら、CDI管理Beanとして扱ったセッションBeanのみが、ManagedBean仕様で定義した振る舞いを網羅しています。そのため例えば、Servletクラス(@WebServlet)はCDI管理BeanやEJBに@Injectによりインジェクション可能ですが、インジェクションするとHTTPリクエストを処理するサービスなど、JavaEEコンポーネントとしての能力が失われてしまいます。

添付のMatrix1を見てください。この表では、JavaEEプラットフォームの管理クラスとCDI機能について、よりわかりやすく示しています。これが現状です。

着目したい点は、CDI管理Bean(含むセッションBean)に適用されているCDI機能は、これらBeanの種類を超えて備えられていますが、統一的に各Beanに機能を適用しているわけではありません。例えば、メッセージ駆動BeanはCDIインターセプタをサポートしていますが、デコレータやオブザーバなどのセッションBeanがサポートしている他のCDI機能をサポートしていません。

JavaEEコンポーネントの中でも整理できていない問題があります。(EJBServletJAX-RSリソースクラス、Webサービスエンドポイント)
例えば、現在はEJBと管理BeanのみがJavaEEインターセプタをサポートしています。JAX-RSエンドポイントは、実装クラスをEJBまたは管理Beanにした場合にインターセプタがサポートされます。Webサービスエンドポイントにおいても、実装クラスをEJBにした場合はインターセプタがサポートされます。

私たちは、現在の状況をクリアにする必要があると考え、CDI管理Bean、JavaEE管理Bean、そしてインジェクションをサポートするコンポーネントクラス、それぞれの概念について整理を図ろうとしています。

私たちは複数の可能性を探っています。

(1) "なにもしない"
プラットフォーム仕様に透明性をもたらすこと以外は何もせず、EJBセッションBean(それと@ManagedBeanも)をCDI管理Beanとして扱った場合のみ、JavaEEで定義されているコンポーネントのすべての振る舞いを維持します。

(2) "第1管理クラスオブジェクトと、第2管理クラスオブジェクトを分ける"
Table EE.5.1で定義されている"component classes"を、コンポーネントコンポーネント補助クラスの2つのグループに分ける案です。エキスパートグループの議論では、"Component class"の定義を現在のコンポーネントの種類よりもっと狭くすることを提案し、EJBServlet、管理Beanと、実装にこれらのJavaEE管理クラスを用いているもの(JAX-RSリソースクラスとWebサービスエンドポイント)に限定します。
これは言い換えると、現在の仕様で明らかとなっている"component classes"を公式のコンポーネントクラスとし、補助的なコンポーネントクラス(e.g. フィルタ、リスナ、インターセプタ、…)と2つの異なるグループに区別するということです。

加えて、JavaEE管理Beanにサポートされる(既にされている)、トランザクション、セキュリティ、非同期呼び出し、タイマとタイマーサービスなどのコンテナサービスについても位置付けを整理します。これらサービスをCDI管理Beanの機能として拡張します。セッションBeanと管理Bean以外のJavaEEコンポーネントCDI管理Beanとして扱った場合の振る舞いは、これまでのものが維持されません(※1)。

注意点としては、トランザクション、セキュリティ、非同期呼び出しはCDIインターセプタ経由のサポートが候補となることです。コンテナ管理イベントのタイマ通知サービスはCDIイベント/オブザーバ機能によってサポートされることが望まれます。
(※1 機能が削られるわけでなく、ServletJAX-RSにインターセプタやタイマが追加されることを意図しています)

Matrix2はこの案を説明したものです。青色背景でハイライトされている部分がMatrix1からの変更点です。
最初の表からの変更点は、ServletJAX-RSリソースクラス、すべてのEJBおよび管理Beanに対してインターセプタのサポートを追加したことです。(この表にタイマサポートを含めていることは可能性について示しているだけであり、現在のところJavaEE7でタイマをサポートするコンポーネントを拡張することについて未計画です。)

MDBが特別扱いでなくなったことについても触れておきます。これはMDBにとって不利益のように見えますが、今までCDI機能が全てのJavaEEコンポーネントに付与されていなかっただけのことです。

(2a) "(2) + ManagedBean仕様を削除する"
管理Beanの概念を意図しているManagedBean仕様のMB.2.2を削除し、JavaEE管理Beanは基本モデルであるということだけを定義します。[この案の表はMatrix2と同じです。]

(3) "JavaEEコンポーネントへのCDI機能のサポートをもっと拡大する"
(2)の変更点に加えて、JavaEE管理BeanとCDI管理Beanの概念を統合して、JavaEEコンポーネントが各々の振る舞いを維持した上で、もっとCDIの機能をサポートする案です。(i.e.インターセプタ、デコレータ、オブザーバメソッド、プロデューサメソッド/フィールドの追加)
他のコンポーネントにインジェクションされる場合の、これらJavaEEコンポーネントの振る舞いについては例外事項となります。例えば、HTTP経由のリモート起動をサポートするWebサービスやJMS、RMIなどは他のBeanに対してインジェクションして含めることはできません。

Matrix3はこの案を説明したものです。緑色背景でハイライトされている部分がMatrix2から拡張された点です。

(4) "コンポーネントとしての振る舞いを持ったままインジェクションする"
(3)に加えて、各JavaEEコンポーネントの振る舞いを維持したままインジェクション可能とします。
例えば、インジェクション経由で獲得したサーブレットインスタンスは、HTTPリクエストによって生成されたものと同じインスタンスであり、他のコンポーネントも同様に各々の振る舞いを維持したままインジェクションされます。

Matrix4はこの案を説明したものです。紫色背景でハイライトされている部分がMatrix3から拡張された点です。

(5) "すべてのJavaEEコンポーネントJavaEE管理Beanとなる"
(2)の変更点に加えて、表EE 5.1に示されているすべてのコンテナ管理クラスに対して、JavaEE管理Beanの概念を追加する案です。
(既にサポートされている)リソースインジェクションに加えて、ライフサイクルコールバック、インターセプタ、タイマサポート、JNDIからルックアップ可能である機能を追加します。機能上の変更点としては、サーブレットフィルタや、リスナ、インターセプタがこれら機能を新たに備えます。

Matrix5はこの案の機能上の変更点を説明したものです。ピンク色背景でハイライトされている部分がMatrix2から拡張された点です。

(6) "すべてを管理Beanとする"
(2)で示した、第1と第2の管理クラス両方を、CDI管理Beanの機能としてサポートする案です。

Matrix6はこの案を説明したものです。Matrix4とMatrix5で拡張した機能を含んでいます。黄色背景でハイライトされたものがMatrix4とMatrix5から拡張された機能です。

みなさんのフィードバックを必要としてます!!
多くの情報を自分の頭で消化することになると思いますが、注意深く検討を進めることためにもみなさんのフィードバックを心よりお待ちしています。この問題は、これから先、JavaEEプラットフォームでサポートする管理Beanの行く末に大きなインパクトを与えるものです。

目を通してくれてありがとう。

リンダより。