はじめに
先日、ある友人が電話をかけてきて、今回のAtlanta JUGミーティングはJBossの新製品「Seam」の情報を得ようとする人々で大変な盛況だったと語りました。私はコンピュータの前に座ってSeamのことを20分ほど調べ、とても好印象を持ちました。SeamはJava EE 5(J2EE 3)の軽量な標準規格をベースにしており、新しいエンティティBean仕様、JSF、アノテーション、インターセプタ、セッションBeanといった技術を使用しています。Springと同様に制御の反転(Inversion of Control)を使用しますが、Springとは異なり、ステートフルなオブジェクトの注入を許可します。エンタープライズJava開発者が7年間もコツコツとやってきたデータ移動とフレームワーク/API操作の作業の多くがSeamによって解消されるのです。
ユースケースとユーザーストーリーは対話的(conversational)なやり方で要件を記録しますが、私の知る限り、Seamは対話的なやり方でコーディング作業を助ける最初の製品です。Seamを利用すると、アプリケーションのページレベルおよびBPMレベルのやりとりが、ファーストクラスのエンティティになり得ます。ユースケースとユーザーストーリーが実際にコードのモデルになるのです。
私は、もし自分の開発チームでSeamを使用していたらこの3年半にどれだけ多くのコードを節約できただろうかと考えてみて、Seamの有効性を実感しました。おそらく40~60%のコードが不要になったと思われます。
その後、実際にSeamを試してみて、コーディングが減って開発が楽になるという話が本当なのだと確認できました。そのことを、本稿で証明したいと思います。
Seamの概要
Seamのメリットはいろいろありますが、私の考える重要な特徴は次の3つです。
- Java EE 5標準に基づいている
- 宣言的状態モデル
- 制御のサブバージョン(バイジェクションともいう)
SeamはJava EE 5仕様の概念をさらに推進し、軽量な開発とプログラマにとっての使いやすさを念頭に置いて設計されています。SeamはJSFとEJBのための強力な統合フレームワークを備えており、普通ならこれらの製品を統合するために使われるグルー(接着剤)コードが不要になります。開発者はオブジェクトからフォームやJSPへのデータ移動に時間を費やす必要がなく、ビジネスの価値を生み出すことに専念できます。
Seamによる統合レベルでのコスト削減の効果は、Seamの基盤であるHibernate/EJB 3エンティティBeanアプローチに最もよく現れています(表1を参照)。Seamにより、JDBC呼び出しからオブジェクトへのデータ移動およびその逆のデータ移動に必要なロジックが不要になります。また、クラスレベルの複雑な関係管理はSeamが担当してくれるので、開発者は、過去のJDBCアプリケーションでこれらの問題を処理するために必要とされたコードや外部キーの詳細を気にせずに済みます。Hibernateはこれらの概念をEJB 3.0仕様と共に導入しましたが、これらはJava標準として採用されています(このモデルの詳細については、「Simplify Java Object Persistence with Hibernate」を参照してください)。
JDBCによる顧客統合管理クラス | 行数 |
AbstractJdbcDao.java | 169 |
CustomersJdbcDao.java | 301 |
ICustomerVO.java | 89 |
CustomerVo.java | 177 |
CustomerComponent.java | 71 |
合計 | 807 |
Hibernateによる顧客管理統合クラス | 行数 |
Customer.java | 179 |
CustomerFinder.java(クエリメソッドのみ、フロントエンド制御ロジックなし) | 66 |
合計 | 245 |
Seamの宣言的状態モデル(図1を参照)では、状態を持つオブジェクトを管理するためのコンテキストを宣言できます。コンテキストになり得るものは、アプリケーション、セッション、対話(conversation)、ページ、イベント、BPMなどです。状態のコンテキストを宣言すると、Seamは必要な間はその状態を保持し、不要になると破棄します。状態管理によって、第2レベルのデータベースキャッシュ、ステートフルセッションBean、またはhttpセッションに関係する多数のバグとパフォーマンス上の問題が解決されます。また、APIの使用に関係するグルーコードも不要になります。
![図1 Seamのモデル:Seamにより、JSFとJava EE 5仕様の他の部分の間のグルーコードの多くが不要になる。Seamは状態のコンテキスト管理を複雑なJava EE 5 Webアプリケーションに取り入れている(出典: JBOSS) 図1 Seamのモデル:Seamにより、JSFとJava EE 5仕様の他の部分の間のグルーコードの多くが不要になる。Seamは状態のコンテキスト管理を複雑なJava EE 5 Webアプリケーションに取り入れている(出典: JBOSS)](http://cz-cdn.shoeisha.jp/static/images/article/484/15714.gif)
制御の反転(IoC)はSpringで広く知られるようになった概念であり、しばしばハリウッドのプロデューサー的な「Don't call me, I'll call you.(電話をかけてくるな。必要があれば僕からかけるから)」という言葉で表現されます。IoCの概念では、ある種の処理をアプリケーションコードから分離してフレームワークまたはコンテナに移し、ある種のAPIの管理をアプリケーションコードからコンテナに移します。依存性注入(dependency injection)はIoCの一種であり、指定されたオブジェクトの作成または管理をIoCコンテナに移します。以前の手法ではオブジェクトのフェッチとAPIを処理するコードを書かなければなりませんでしたが、依存性注入では、使用すべきオブジェクトが判断され、そのオブジェクトが作成または取得されて、アプリケーションコードに与えられます。これにより、アプリケーションコード内のオブジェクトが、そのオブジェクトを作成するAPIに依存しなくなります。
IoCと依存性注入という概念の利点は、制御のサブバージョン(subversion of control:SoC)とバイジェクション(bijection)の機能を備えたSeamにはっきりと表れています。IoCとSoCの違いは、オブジェクトを注入(inject=インジェクト)できるだけでなく、その逆方向の注入(out-ject=アウトジェクト)もできる点にあります。IoCコンテナは単一のインスタンスを作成または再使用し、そのリソースを必要とするオブジェクトにインジェクトします。アウトジェクトでは、注目すべき状態が含まれているオブジェクトを、後でインジェクトに使用するためにコンテナに入れることができます。IoCではリソースをオブジェクトに注入するだけですが、Seamでは両方向の注入が可能です。
Seamはインジェクションを遂行するために次のアノテーションを使用します。
@Name
と@Role
@In
@Out
@Scope
@Scope(CONVERSATION)
@Name
で識別)を宣言的状態管理フレームワークに入れます。Seamでは、EJB 3.0のアノテーションとSeam独自のアノテーションを広範囲にわたって使用します。データベースマッピングとその他のAPIコンフィグレーション情報をアノテーションで指定することにより、サードパーティのフレームワークを使用する際の煩雑さが軽減されます。また、コードが別のXMLファイルに分離されないので、コードが理解しやすくなります。
SoCと宣言的状態モデルの組み合わせは非常に強力です。これにより、対話的なやり方でコーディングを行うことができます。複雑なページフローも簡単に作成することができ、特に、ネイティブな統合を実現しているJBossのjPDL製品を使用すればさらに効率が上がります(図2を参照)。古いプログラミングモデルではBPMタイプのツールをうまく活用できませんでしたが、JBossのjBPMはこのプログラミングモデルにたやすく適合します。
Seamによるページフローの管理
Seamでページフローを管理する方法は2通りあります。1つはごく初歩的な方法で、ボタンを押すと、文字列が渡され、その文字列が次のページにマップされるという仕組みです。この文字列を返すルーチンに、複雑なページフローロジックが記述されています。次に示す例では、基本的なXMLファイルを使用しています。これは「ステートレスナビゲーションモデル」とも呼ばれます。
<navigation-rule> <navigation-case> <from-outcome>editCustomer</from-outcome> <to-view-id>/editCustomer.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>selectCustomer</from-outcome> <to-view-id>/findCustomer.jsp</to-view-id> </navigation-case> <navigation-case> <from-outcome>findCustomer</from-outcome> <to-view-id>/findCustomer.jsp</to-view-id> </navigation-case> </navigation-rule> <navigation-rule> <from-view-id>/editCustomer.jsp</from-view-id> <navigation-case> <from-outcome>find</from-outcome> <to-view-id>/findCustomer.jsp</to-view-id> </navigation-case> </navigation-rule>
Seamのもう1つのページフローモデルは「jPDL」と呼ばれます。jPDLは、プロセス定義言語を定義するXMLファイルです。jPDLには優れたグラフィカルインターフェイスが用意されており、複雑なページフローを扱う際に大いに役立ちます。