JBoss Seam ~Java EEは統合フレームワークへ~
統合的なフレームワークを目指すJava EE
Java EE 5という標準規格が策定された経緯について第1回で説明しましたが、Java EE 5で行われた作業は、まさに標準規格の「再整理」と呼べるものでした。
誕生当初から次代のJava EE(このころは、まだJ2EEと呼ばれていた)の中核を担う技術として注目を集めていたJSF 1.2がプレゼンテーション層のフレームワークとして正式に採用され、Java EEの本体とも言えるEJBはDIコンテナの機能を取り込み、生産性を飛躍的に向上させたEJB 3.0として大きく生まれ変わりました。
また、それまでCMP Entity BeanとしてEJB仕様の一部として存在していたO/Rマッピング機能は、Java EEとは独立して発展し続けてきたHibernateやTopLinkといったオープンソースのO/Rマッピング・ツールに歩み寄る形で新たに策定され、EJBとは独立したAPIであるJPA 1.0に役割を委ねることになりました。
このように機能の統廃合や、Java EE以外のコミュニティのノウハウの取り込みを行うことによって、JSF 1.2 - EJB 3.0 - JPA 1.0というスタックを築き上げたJava EE 5ですが(図1)、既に米JBossのGavin King氏には、これらのスタックをシームレスにつなげ、統合的なWeb開発フレームワークとして提供するという、次のJava EE 6に向けた青写真がありました。
この青写真を具現化したものが、同氏が開発したJBoss Seam(以下、Seam)というWeb開発フレームワークであり、それを基にして同氏が策定し、Java EE 6に採用されることになった「JSR-299:Context and Dependency Injection for Java EE Platform」(以下CDI)です。
連載2回目となる今回は、今後のJava EEの歩みにおいて大きな鍵となるであろう、Seamについてご紹介いたします。
JBoss Seamとは
Seamは、JBoss Application Serverなどと同様に、JBossコミュニティで開発されているオープンソース・プロダクトです。ライセンス形態はLGPL(GNU Lesser General Public License)であり、無償での入手、利用が可能ですが、米Red Hat(2006年に米Red Hatが米JBossを買収)の有償サポートを受けることも可能です。
Seamは、JBoss Application Serverはもちろん、それ以外のJava EE 5に準拠したアプリケーション・サーバー上でも動作させることが可能なWeb開発フレームワークであり、以下のような特徴を持っています。
- 付属ツールのseam-genによってアプリケーションのひな型を作成でき、簡単に開発が始められる。
- JSFとEJBをシームレスにつなぐ機能を持つ。
- 独自のコンポーネント・モデルによって、ステートフルなWebアプリケーション開発を容易にする。
次ページからこれらの特徴について解説しますが、ここではまず、開発環境について簡単に紹介します。
前述のように、Seamはさまざまな環境で動作させることが可能ですが、一番簡単に動作させるためには、JBoss Application Serverを使用するのが良いでしょう。JBoss Application ServerにはDBMS(HSQLDB)もバンドルされているので、SeamとJBoss Application Serverに加えて、JDKを用意すれば、Seamのすべての機能を確認できます。
参考までに、今回、動作確認に用いたソフトウエアは以下の通りです。
- JBoss Seam 2.2.0
- JBoss Application Server 5.1.0
- JDK 5.0 UPDATE 21
SeamとJBoss Application Serverは、適当な位置に解凍するだけで構いません。JDKはインストール後、環境変数「JAVA_HOME」を適切に設定します。事前準備はこれだけです。
seam-genを使ってアプリケーションのひな型を作成する
本記事の読者の中には、Ruby on RailsというRuby言語で開発されたWeb開発フレームワークのことをご存じの方も多いかと思います。Ruby on Railsがscaffoldという機能を使ってアプリケーションのひな型をコーディングレスに作成できるように、Seamでもseam-genを使ってアプリケーションのひな型をコーディングレスに作成できます。
まず、解凍されたSeamのディレクトリ直下に、seamあるいは、seam.batというコマンドが用意されていますので、コマンド・プロンプトから、
--------------------------------------------------------------------------------
./seamsetup−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−を実行すると、対話形式で環境セットアップを行うことができます。プロジェクトのホーム・ディレクトリ(以降、「{PROJECT_HOME}」)とJBossのホーム・ディレクトリ(「以降、${JBOSS_HOME}」)を適切に指定し、デプロイ形式はEJBを使用するので「ear」を選択し、それ以外はデフォルトのままで構いません。
セットアップが完了した後、
--------------------------------------------------------------------------------
./seamcreate−project−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−を実行すると、ひな型アプリケーションの含まれたプロジェクト・ディレクトリが「{PROJECT_HOME}/myproject」に作成されます。
--------------------------------------------------------------------------------
$ ./seam deploy
--------------------------------------------------------------------------------
を実行すると、プロジェクトのビルド、およびアプリケーション・サーバーへのデプロイが実行されますので、アプリケーション・サーバーを起動し「http://localhost:8080/myproject/」にアクセスしてみてください。「Welcome to Seam!」という画面が表示されれば成功です。
これだけでは味気ないので、フォーム・アプリケーションのひな型も作成してみましょう。アプリケーション・サーバーを停止して、先ほどと同じプロンプトから、
--------------------------------------------------------------------------------
$ ./seam new-form
--------------------------------------------------------------------------------
を実行します。Seamコンポーネント(次項で説明します)の名前を聞いてくるので、ここでは「hello」としましょう。あとはデフォルトのままで構いません。コマンドが完了すると、先ほどのプロジェクト・ディレクトリに、リソースが追加されます。
先ほどと同じ手順で、ビルド、デプロイを行い、アプリケーション・サーバーを起動して「http://localhost:8080/myproject/hello.seam」にアクセスしてみてください。表示された画面のフォームに文字列を入力し、「hello」ボタンをクリック、入力した文字列が上部のステータス・メッセージに表示されれば成功です(図2-1)。
ここでは割愛しますが、scaffoldと同様に、CRUD(Create, Read, Update, Delete)アプリケーションのひな型をseam-genを使って作成することもできます。このようにして作成されたアプリケーションのひな型は、これらを基にして開発を始めることで、開発効率を上げることができるとともに、Seamの機能を把握するためにも大いに役に立つことと思います。
次項からは、seam-genによって作成されたアプリケーションのひな型を参考にして、Seam本体の機能について紹介します。
JSFとEJBをシームレスにつなぐ
Seamの名の通り、JSFとEJBをシームレスにつなぐことができるということが、Seamの大きな特徴であると言えます。この点について、Seamが果たす役割について説明する前に、まずはSeamを用いない場合の開発について整理してみます。
JSFでは、Managed Beanと呼ばれるJava Beansを媒介にして、ビジネス層へのデータの受け渡しを行います。もちろん、Managed Bean自体がビジネス・ロジックを持っても構わないのですが、ここで注意しなければならないのは、Managed Beanとして登録できるのは、あくまでJava Beansであり、EJBではないということです。ビジネス・ロジックをEJBとして実装する場合には、やはり、パラメータの受け渡しのみを目的としたManaged Beanを作成せざるを得ないということになります。また、Managed Beanの作成には、faces-config.xmlの記述という煩わしい作業がつきまといます。
Seamを使用した場合、これらの作業はどう変わってくるのでしょうか。先ほど作成したフォーム・アプリケーションのひな型を見てみましょう。
まず、「PROJECTHOME/myproject/resources/WEB−INF/faces−config.xml」のどこを見ても、ManagedBeanに関する記述は見当たりません。次に、「{PROJECT_HOME}/myproject/src/hot/com/mydomain/myproject/action/HelloBean.java」を開くと、ソースの13行目に「@Name("hello")」というアノテーションが付加されているのが分かります。
結論から言いますと、Seamを使用した場合、Managed Beanを登録するためのfaces-config.xmlの編集作業は必要ありません。@Nameアノテーションが付加されたクラスは、Seamコンポーネントと呼ばれ、Managed Beanの役割を果たすようになります。要するに、@Nameアノテーションは
また、このソースでは省略されていますが、「@Scope(SESSION)」というようなアノテーションを付加することによって、若干意味合いは異なりますが(次項で説明します)、
もう1つ、このソースで注目すべき個所は、12行目の@Statefulアノテーションです。そう、このクラスはEJBなのです。Seamでは、EJBもJava Beansと同様にSeamコンポーネントとして登録することができ、JSFからのパラメータを直接受け取ることができるのです(図2-2、2-3)。
このように、Seamはアノテーションを活用することによって、faces-config.xmlを記述する手間を減らし、さらにはEJB呼び出しを隠ぺいし、Managed BeanとEJBの役割をSeamコンポーネントとして統合することで、冗長なManaged Beanを作成する手間を省いてくれるのです。これが、JSFとEJBをシームレスにつなぐSeamの果たす大きな役割です。
次ページでは、ステートフルなWebアプリケーション開発を効率化するSeam独自のコンポーネント・モデルについて解説します。
JBoss Seamのコンポーネントモデル
Seamはコンテキスト依存(contextual)コンポーネント・モデルという独自のコンポーネント・モデルを持っています。このコンポーネント・モデルは、従来のJava EE上でステートフルなWebアプリケーションを開発するうえでの問題を解決し、さらに対話(conversation)という新たな概念によって、ステートフルなWebアプリケーション開発を飛躍的に効率化させるために導入されました。以下では、このSeam特有のコンポーネント・モデルについて紹介します。
まず、前述の「@Scope(SESSION)」というアノテーションは、一体「何の」スコープを指し示しているのでしょうか。その答えがコンテキストです。
SeamはApplication、Session、Conversationなど(最初の2つはServlet APIでなじみ深いものだと思います)のさまざまなスコープを持ったコンテキストを持っており、すべてのSeamコンポーネントのインスタンスは、いずれかのコンテキスト上で管理されています。Seamコンポーネントは、それぞれのタイミングでインスタンス化(初回の呼び出し時に作成、明示的に作成)およびコンテキスト上で管理され、コンテキストのスコープが終了(セッションの終了、リクエストの終了)するとともに破棄されます。
Seamコンポーネントは、コンテキスト上で、コンテキスト変数と呼ばれる名前つき変数(@Nameアノテーションで指定した名前)の中に格納され、EL式(Expression Language)の中から変数名で参照することができます。
また、インジェクション用のアノテーション(@In)を使用することによって、指定したプロパティへコンテキスト変数から値を差し込むことができ、逆にアウトジェクション用のアノテーション(@Out)を使用することによって、指定したプロパティからコンテキスト変数へ値を差し込むこともできます。このような機能をバイジェクションと呼んでいます。
インジェクションはコンポーネント・ツリーを構築するための重要な機能ですが、インジェクションで重要なことは、そのプロパティを持つコンポーネントがインスタンス化された時に行われるのではなく、そのインスタンスが呼び出される際に毎度行われるということです(ちなみにアウトジェクションはインスタンスの呼び出しが終了した際に行われます)。この仕組みによって、スコープの異なるコンポーネントがインジェクトされる場合でも、整合性を損なうことなくコンポーネントを構築でき、faces-config.xmlにおいて長さの異なるスコープのManaged Beanを
Seamのコンテキストのなかでも、特に特徴的な概念が、Conversation(対話)です。
Conversation(対話)は、Seamのコンポーネント・モデルの中核をなす概念であり、今までのJava EE開発にはなかった新たな概念です。対話コンテキストのスコープは複数のリクエストにまたがりますが、Sessionスコープよりは短く、ユーザーが1つのウィンドウの中で行う、不可分な作業単位を表します。
例えば、ユーザー登録機能が複数ページに亘って行われるようなアプリケーションにおいて、最初の画面のサブミットから、最後の画面のサブミットまでは、対話であると考えることができます。こう書くと今までSessionスコープで管理していたほとんどのものは、対話スコープで管理すべきなのではないかと思われるのではないでしょうか。
アプリケーションのひな型を使って、具体的なイメージをつかんでみましょう。
--------------------------------------------------------------------------------
$ ./seam new-conversation
--------------------------------------------------------------------------------
を実行します。フォーム・アプリケーションの場合と同じように、Seamコンポーネントの名前を聞いてきますので、「counter」と入力しましょう。あとはデフォルトで構いません。
先ほどと同じ要領で、ビルド、デプロイを実行した後、「http://localhost:8080/myproject/counter.seam」にアクセスすると、数値「0」が表示されたパネルと、「Begin」ボタンがページに表示されます。「Begin」ボタンをクリックすると、「Increment」ボタンと「End」ボタンが表示されます。「Increment」ボタンをクリックする度に、パネルに表示された数値は増加していき、「End」ボタンをクリックするとトップのページに遷移します。上部の「counter」リンクを選択し、再び先ほどの画面に戻ると、画面は初期状態に戻っています(図3-1)。
この単純なアプリケーションにおいて、「Begin」ボタンをクリックしてから「End」ボタンをクリックするまでの間、パネルに表示される数値は、対話コンテキストで管理されています。
「${PROJECT_HOME}/myproject/src/hot/com/mydomain/myproject/action/CounterBean.java」を見てみましょう。begin()、increment()、end()と、各ボタンに対応するアクション・メソッドが並んでいますが、begin()メソッドの上には@Beginアノテーションが、end()メソッドの上には@Endアノテーションが付加されているのが分かります。対話コンテキストは、このようにアノテーションによって開始と終了を宣言することにより管理します。HTTP Sessionを自前で管理しなくても、アノテーションを付加するだけで、このようなアプリケーションが作れるのです(図3-2、3-3)。
とはいえ、この程度であれば、HTTP Sessionで管理しても大した手間ではないのではないかと思われる方もいらっしゃるかもしれません。そのような方は、アプリケーションを複数のタブで開いて動作させてみてください。それぞれのタブで開かれたカウンターが互いに独立して数を増やしていくのが確認できると思います。Seamでは、同一セッション上で並行して進行するような対話にも簡単に対応できるのです。
Weld、そしてJBoss Seam 3へ
ここまで、Seamの持つ3つの特徴を中心に説明してきましたが、特に後半の2つ、
- JSFとEJBをシームレスにつなぐ機能を持つ。
- 独自のコンポーネント・モデルによって、ステートフルなWebアプリケーション開発を容易にする。
は、2009年12月にリリースされたJava EE 6に採用されている仕様、CDIの中でも中核をなす重要な機能になります。アノテーションやAPIについては仕様の策定にあたって調整が行われたため、Seamの機能がそのままJava EE 6として採用されているわけではありませんが、概念や機能の大枠はSeamのそれと大差はありません。
また、現在Seamコミュニティでは、次期バージョンであるSeam 3.0に向けて開発が行われている最中ですが、CDIのリファレンス実装(参照実装)であるWeldがそのままSeam 3.0のコアとして採用され、JavaEE 6準拠のWeb開発フレームワークとなる予定です。
Seamは、CDIの部分以外にも、Seam-genをはじめとするツール、ユーティリティ群を豊富に備えており、Java EE準拠のWeb開発フレームワークとして、最も実用に耐えうる、現実的なものであるといえます。
本記事では、Seamの概要をご紹介しましたが、もっと詳しい内容や技術を確認されたい方は、野村総合研究所(NRI)の開発エキスパート達が執筆した「JBoss Seam」の入門書がありますので、ぜひご一読ください。実用的なサンプルアプリケーションの作成方法を交えながら、Java EE 6時代の中核となる標準技術を解説しています。
『オープンソース徹底活用 JBoss Seamによる Webアプリケーション開発』
次回は、NRIがSeamを使ってSI(システム・インテグレーション)での開発向けに提供しているWeb開発フレームワークについて紹介します。