はじめに
業界全体がより生産性の高いソフトウェア開発手法を追求する中で、Javaコミュニティは、エンタープライズ開発の技術的に難しい問題(分散トランザクション管理、並列性、オブジェクト分散など)に対するソリューションとして、J2EEに期待を寄せてきました。J2EEの背後にある考え方、つまり「複雑なエンタープライズサービスの実装はアプリケーションサーバーのベンダが行い、それをビジネスアプリケーションの開発者が利用する」という考え方は、非常に合理的です。J2EE(特にEJB)は、エンタープライズJavaアプリケーション構築のための優れたプラットフォームを提供してきました。
この成功の一部を支えているのは、宣言型プログラミングが可能になったことです。宣言型プログラミングとは、インフラストラクチャサービスの明示的なコーディングの中にビジネスロジックを組み込むのではなく、インフラストラクチャサービスを宣言することによってプログラムを開発するスタイルです。この開発スタイルの真価はEJBによって証明されました。EJBにより、トランザクションやセキュリティといったエンタープライズ機能を配備記述子の中で宣言し、コンテナから制御できるようになったのです。
しかし、ここ数年、EJBに由来する一連の問題がチームの生産性に影を投げかけていると考える開発者が増えつつあります。EJBはそれぞれが複数のインターフェイスを伴い、それを配備記述子の中で宣言し、JNDIなどからアクセスする必要があります。コンテナの外でEJBの単体テストを行おうとするとさらに面倒なことが起こり、EJBは純粋な意味でのオブジェクト指向開発から逸れつつあります。EJBをめぐる論争については、関連記事を参照してください。
必要な環境
EJB 3.0について
EJB 3.0は、次の仕組みを用いてエンタープライズ開発を支援することを目指しています。
- エンタープライズサービスを宣言的に要求するメタデータアノテーションの導入
- アノテーションによる依存性/リソース注入
- EJB固有のインターフェイスからのエンタープライズBeanの分離
- 軽量なオブジェクト関係マッピングによる持続性の簡易化
これは、EJBの開発、テスト、メンテナンスに取り組んできたEJB開発者にとっては大きな福音です。EJB 3.0を使うと、エンタープライズBeanの作成は、従来の普通のJavaオブジェクト(Plain Old Java Object:POJO)と同じくらい単純化されます。特別なアノテーションを用いてEJBとして宣言し、エンタープライズサービスを要求するだけで済むのです。以下は、EJB 3.0 Public Draftに記述されているEJBの例です。
@Stateful public class CartBean implements ShoppingCart { private float total; private Vector productCodes; public int someShoppingMethod(){...}; ... }
EJB 3.0の仕様は、基本的に、開発者が求めるのは何にでも対応可能な重量級ソリューションではなく、必要な範囲のエンタープライズサービスだけをカバーし、しかも簡単に使える軽量ソリューションである、という認識に立っています。この要件を満たすために、EJB 3.0では、エンタープライズBeanとEJB APIを分離することが特別重要な意味を持ちます。また、このソリューションによって興味深い副次効果がもたらされます。つまり、EJBをさまざまなEJBコンテナで実行できることはもちろんですが、エンタープライズサービスの宣言に使われるEJB 3.0(JSR 220)と共通アノテーション(JSR 250)を認識するフレームワークさえであれば、どんなアプリケーションフレームワークでもEJBを実行できるわけです。
本稿では、宣言型プログラミング、EJB、アスペクト、アノテーションの詳しい説明は省きます。それよりも、これらのテクノロジの相互関係に焦点を当て、これを斬新な方法で組み合わることでアプリケーション開発がいかに簡素化されるかを示します。
本稿では、EJB 3.0互換のBeanを作成し、このBeanを簡単なアスペクトを用いて配備し、宣言的なトランザクション管理、セキュリティ、リソース注入を実現します。この演習で次のことを学習できます。
- アスペクトの応用例(依存性注入、セキュリティ、トランザクション)を知る。
- EJB 3.0とその背景にある考え方に慣れる。
- EJBを特定APIから分離することでEJB 3.0対応サービスの実装が軽量化され、EJB以外のフレームワークにも応用可能になることを理解する。
サンプルアプリケーション:航空券予約
以下、本稿では航空券予約システムを例にとり、アスペクトとアノテーションを用いて依存性注入、セキュリティ、トランザクション管理を実装することを考えます。このアプリケーションには2つの機能しかありません。つまり、ユーザーが便名を検索する機能(図1)と、予約を入れる機能(図2)です。どちらの操作も、登録済みユーザーだけが実行できるよう保護されます。また、この「旅券予約」操作では2つの便(往路と復路)の予約を必須とするため、トランザクション的な処理が必要になります。つまり、2つの予約をひとまとまりと見なし、両方が成功するか失敗するようにしなければなりません。
この簡単なWebアプリケーションは、2つのサーブレット、1つのサービスファサード、そして1つのDAOレイヤから構成されます(図3を参照)。
リソース設定、セキュリティ、トランザクション管理という分野横断的な関心事は、AspectJ 1.5 M3で実装されているアスペクトによって配備されます(このアスペクトにより、Java 5アノテーションの中で宣言されたビヘイビアが注入されます)。本稿の冒頭で紹介しているリンクからサンプルコードをダウンロードし、Maven 2.0でビルドしてください。