目次


Java EE 5: その威力と生産性、そして軽減された複雑さ

Java EE 5 の機能強化と開発者の生産性向上についての概要

Comments

はじめに

Java EE 技術は、スケーラブルで強力かつ移植可能なエンタープライズ・アプリケーションの作成を可能にする Java 言語プラットフォームの拡張です。アプリケーション・コンポーネントのコンテナーとしては、Web、EJB (Enterprise JavaBean)、アプリケーション・クライアント、アプレットの 4 つが定義されています。この 4 つのコンテナーと各コンテナーがサポートする Java API はアプリケーション・サーバー仕様に詳説されていることから、Java EE 製品の競争市場は促進され、それと同時にこの仕様に準拠したアプリケーションのサーバー移植性も保証されます (「Java EE の歴史概略」を参照)。

最新バージョンのプラットフォーム、Java EE 5 は 2006年5月にリリースされました。開発者の生産性を最大の重点とした Java EE 5 は、プラットフォームの威力と充実した機能を一切犠牲にすることなく、単純化したプログラミング・モデルを実現しています。この開発モデル単純化の大部分を支えているのは、Java アノテーションと改善されたデフォルト設定という 2 つのメカニズムです。主な機能改善には、Web サービス・サポートの強化、そしてプラットフォームへの JSF (JavaServer Faces) および JSTL (Java Standard Tag Library) の統合が含まれます。

この記事では、前回の J2EE リリースからの変更内容を中心に Java EE 5 の機能を探っていきます (強化された機能のうち、この記事で取り上げないものには、StAX API (XML のプル型構文解析 API) の追加、そして多くの API で行われた小規模から中規模の改善が含まれます)。まず、Web サービス、Web アプリケーション、エンタープライズ、管理およびセキュリティーの 4 つの機能分野の全体像について説明してから、「簡単な実例」として Java EE 5 の機能を利用する小さなアプリケーションを例に、サービス指向アーキテクチャー (SOA) を用いた Web アプリケーションの単純化された開発モデルについて説明していきたいと思います。

この記事では、エンタープライズ・レベルのソフトウェア・システムについて十分な知識がある上で、包括的な Java EE 5 の概要を知りたいという読者を対象としています。機能の概要を理解するには、Java プログラミングと J2EE に関する実用的な知識があると役立ちますが、必須というわけではありません。サンプル・アプリケーションについては技術的詳細に踏み込んで説明します。これらの詳細は、おそらく J2EE (少なくとも Java プログラミング)のバックグラウンドを持った人には参考になるはずです。

Web サービスの技術

Java EE 5 にアノテーションが導入されたことにより、以前の Java EE バージョンと比べ、高度な Web サービス・エンドポイントとクライアントを少ないコードと短い学習曲線で簡単に作れるようになっています。 Java SE 5 で初めて導入されたアノテーションとは、メタデータとしてコードに追加できる修飾子のことです。アノテーションはプログラムのセマンティクスには直接影響しませんが、コンパイラー、開発ツール、ランタイム・ライブラリーはアノテーションを処理することによって、アノテーションが含まれるコードを増補する追加の Java 言語ソース・ファイル、XML 文書などの成果物や振る舞いを作成することができます (「参考文献」を参照)。この記事の後半では、単純なアノテーションを追加して正規 Java クラスを簡単に Web サービスに変換する方法を説明します。

Web サービス・サポートの飛躍的前進

Java EE 5 での Web サービス・サポートの基盤となるのは、JAX-RPC 1.1 の後継である JAX-WS 2.0 です。この 2 つの技術はいずれも、Web サービスに付きものの厄介な XML 処理やデータ・バインディングを直接扱うことなしに RESTful な Web サービスや SOAP ベースの Web サービスを作成できるようにするためのものです。開発者は引き続き JAX-RPC (Java EE 5 コンテナーには依然として必須) を使用することもできますが、JAX-WS に移行することを強くお勧めします。Java Web サービスに初めて関わるのであれば、JAX-RPC を飛ばして JAX-WS から使い始めるとよいでしょう。しかしいずれの場合にしても、この 2 つの技術はどちらも SOAP 1.1 over HTTP 1.1 をサポートするため完全に互換性があるということを知っておいてください。つまり、JAX-WS の Web サービス・クライアントが JAX-RPC の Web サービス・エンドポイントにアクセスすることも、あるいはその逆も可能だということです。

以下に挙げるように、JAX-WS には JAX-RPC に勝る強力な利点があります。

  • SOAP 1.2 標準のサポート (SOAP 1.1 とは別に)
  • XML over HTTP のサポート。必要に応じて SOAP を迂回できます (詳しくは記事「Use XML directly over HTTP for Web services (where appropriate)」を参照)。
  • データ・マッピング・モデルとして JAXB (Java Architecture for XML Binding) を使用。JAXB は XML スキーマを完全にサポートし、パフォーマンスに優れています (詳細はこの後説明)。
  • サーバーとクライアントの両方に動的プログラミング・モデルを導入。クライアント・モデルはメッセージ指向の手法と非同期の手法の両方をサポートします。
  • MTOM (Message Transmission Optimization Mechanism) のサポート。これは、SOAP メッセージの送信およびフォーマットの最適化を目的とした W3C 勧告です。
  • Web サービス・インターオペラビリティー (WS-I) サポートのアップグレード。Basic Profile 1.1 をサポートします。JAX-WS でサポートするのは Basic Profile 1.0 のみです。
  • SOAP 添付サポートのアップグレード。SAAJ (SOAP with Attachments API for Java) 1.3 を使用します。JAX-WS では SAAJ 1.2 しかサポートしていません。

JAX-RPC と JAX-WS の違いについてさらに詳しく調べるには、記事「Web サービスのヒント: JAX-RPC と JAX-WS」を読んでください。

JAX-WS の wsimport ツールは Web サービス開発でありがちな詳細の多くを自動的に処理し、プラットフォームに依存しないように容易にビルド・プロセスに統合するため、開発者はサービスを実装または使用するアプリケーション・ロジックに専念することができます。このツールは、サービスなどの成果物、サービス・エンドポイント・インターフェース (SEI)、非同期応答コード、WSDL 障害に基づく例外、そして JAXB によってスキーマ・タイプにバインドされた Java クラスを生成します。

JAX-WS はまた、パフォーマンスに優れた Web サービスも実現します。新しい JAX-WS スタック (Java EE 5 に用意された別の 2 つの機能、JAXB と StAX を使用) をベースとした場合と J2EE 1.4 で使用可能な JAX-RPC スタックをベースとした場合の Web サービス実装のベンチマーク研究を紹介する記事 (「Implementing High Performance Web Services Using JAX-WS 2.0」) を参照してください (リンクは「参考文献」に記載)。この研究によって、JAX-WS を使用すると、負荷状態が異なるさまざまな機能分野でのパフォーマンスが 40% から 1000% 改善されることが判明しています。

Web アプリケーションの技術

Java EE 5 では主要な 2 つのフロント・エンド技術、JSF と JSTL を仕様に迎え入れ、既存の JavaServer Pages 仕様と Servlet 仕様を結合しています。JSF はコンポーネント・ベースの手法でユーザー・インターフェースの開発を可能にする一連の API で、もう一方の JSTL は JSP において、手続き型ロジック、JavaBean へのアクセス、SQL コマンド、ローカライズしたフォーマット命令、そして XML 処理などの組み込みをサポートするタグ・ライブラリーのセットです。JSF、JSTL、JSP の最近のリリースのほとんどでは、これらの技術をさらに容易に統合できるように統一された式言語 (EL) をサポートしています (「参考文献」を参照)。

JSF 1.2

JSF には、コンポーネントの状態管理、イベント処理、ナビゲーション、ユーザー入力の検証、国際化対応などといった共通する UI 事項のサポートが組み込まれています。したがってベテランの開発者は、カスタマイズした強力かつ再利用可能なコンポーネントを作成したり、あるいは Web ブラウザー以外のクライアント・デバイス用にカスタム・レンダラーを作成したりすることができます。技術を専門としていないユーザーでも、HTML インターフェースのデフォルト JSF タグ・ライブラリーといったカスタム・コンポーネントを Sun Java Studio Creator などのビジュアル・プログラミング環境で再利用できるため、新米プログラマーでも高度な Web プレゼンテーション層を作成できます。

サード・パーティーの JSF コンポーネントは、オープン・ソース・コミュニティーでもライセンス・ソフトウェアの領域でも増えてきています。Web で「JSF コンポーネント」、あるいは「JSF コンポーネント・ライブラリー」を検索すると、いくつもの選択肢が見つかるはずです。これらのコンポーネントの多くは、「Web 2.0」エクスペリエンスの原動力である Ajax (Asynchronous JavaScript + XML) 手法を使用しています。Web プログラマーがこのようなコンポーネントを使えば、Ajax コンポーネントを最初から作成する際の細々とした作業に四苦八苦することなく、従来の Web アプリケーションよりもユーザー・エクスペリエンスに優れたアプリケーションを作成することができます。

JSP 2.1

J2EE 2.1 の頃から使われている JSP 技術は、Java Servlet 仕様を利用して UI の宣言型プログラミングを可能にします。この技術では UI を文書としてプログラミングし、その文書を Java サーブレットに変換してコンパイルし、Web アプリケーション・コンテナーで呼び出して要求に対応させることができます。通常、これらの文書には JSP ディレクティブとスクリプトレットが HTML などのプレゼンテーション・マークアップ言語と混在しています。JSP では <% で始まって %> で終わる特殊なタグに依存する古い構文も、それよりも新しい整形式 XML の構文も使用することができます。一般に、JSP はモデル・ビュー・コントローラー (MVC: Model-View-Controller) UI フレームワークの「ビュー」として機能します。

JSP 2.1 と JSF 1.2 にはそれまでのリリースにも増して互換性があります。その理由は主として、この 2 つの EL 構文が統一 EL に統合されているためです。EL では、例えば以下のオペレーションが可能です。

  • リクエスト、セッション、アプリケーション・コンテキスト内で JavaBean のプロパティーにアクセスする。
  • 特定の要素を非表示にするかまたは表示するかなどを判断する論理テストを実行する。
  • UI に現れる数値およびストリングを左右する計算を実行する。

かつて JSP と JSF には、EL構文やコンテナーが構文を評価する方法に違いがありました。統一 EL はこのような違いを克服するともに、以下をはじめとする機能を追加します。

  • EL 解釈のカスタマイズを実現する交換可能なフレームワーク
  • 必要に応じて JSP タグ・ハンドラーで実行できる据え置き表現のサポート
  • 例えば EL 式を使って JSP コード内から JavaBean にプロパティーを設定するなどといった割り当て操作のサポート

JSP タグ・ライブラリー開発者にとってありがたいのは、タグ・ハンドラーがアノテーションによるリソース注入をサポートするようになったため、これまではリソースの構成と JNDI (Java Naming and Directory Interface) ルックアップを実行するコードとを必要としていたタグを大幅に単純化できるという点です。

JSTL 1.2

JSTL は今まで何年も使用されてきましたが、Java EE 5 が登場するまでは Java EE の傘下には入っていませんでした。JSTL タグは、JSP に以下のような要素を組み込むためのサポートを提供します。

  • 手続き型ロジック。ループや if/else 切り替えなど
  • JavaBean へのアクセス。動的データを UI に提供したり、UI コードによって変更したりすることが可能
  • SQL コマンド。データベース・アクセスを実行
  • フォーマット命令。特定のロケールに応じて UI 出力をフォーマット設定
  • XML 処理。DOM (Document Object Model) 解析や XSL (Extensible Stylesheet Language) 変換など

メンテナンス・リリースである JSTL 1.2 は統一 EL をサポートするため、かつては JSF のタグと JSTLの 繰り返しタグを同じ JSP ページに混在させようとしたときに生じた問題が解決されています。

Java Servlet 2.5

Web 層技術を支える Java Servlet 仕様は、Java EE 技術と同時に登場しました。この仕様は、パフォーマンスに優れたコンポーネント・ベースの手法により、仕様を実装するサーバー間で移植可能な Web アプリケーションを構築できるようにすることを目的としています。

Java EE 5 に必要な Servlet 2.5 仕様は、2.4 リリースを多少改善したメンテナンス・リリースです。このリリースには Java 5 プラットフォームへの依存性とともにアノテーションが導入されているため、Web アプリケーション・デプロイメント記述子 (web.xml) の構成ファイルで必要な構成作業が少なくなります。また、ワイルドカードと複数の url-pattern 要素によって柔軟性がさらに増したサーブレット構成など、利便性も向上しています。

エンタープライズ・アプリケーションの技術

エンタープライズ・アプリケーションの技術として分類される技術は数多くあり、その多くは Java EE 5 リリースの場合でも同じか、あるいはこの記事で取り上げるには細分化されすぎています。そこで、ここでは 2 つの主要な改善点である EJB 開発の容易さと新しいパーシスタンス機能に重点を絞って説明します。

EJB 3.0

EJB 仕様は Java EE プラットフォームの中核です。この仕様は同時データ・アクセスによってデータが壊れないようにアプリケーションのビジネス・ロジックをカプセル化し、極めてスケーラブルでセキュア、かつトランザクションを認識した方法でビジネス・ロジックを配布する方法を定義します。

EJB には、以下の 3 つの基本タイプがあります。

  • セッション Bean。ステートレスとステートフルの 2 つのフレーバーがあります。ステートレス・セッション Bean は、クライアント・コードからの単一のリクエストに対応するビジネス・ロジックのタスクに使用します。もう一方のステートフル・セッション Bean はクライアントとの「対話状態」を維持するため、複数のクライアント・リクエストにまたがる一連の関連タスクに便利です。セッション Bean は、クライアント間では共有することができません。セッション Bean は通常、1 つまたは複数のエンティティー Bean に作用します。
  • エンティティー Bean。通常はデータベースからロードされる永続データを表します。エンティティー Bean はクライアント間で共有することが可能です。そのため EJB 仕様では、エンティティー Bean が壊れることなく安全に複数の同時クライアント・リクエストに対応できるようにするためのトランザクション・セーフ・メカニズムを規定しています。エンティティー Bean の永続性は、エンティティー Bean 自体が管理することも、コンテナーが管理することもできます (コンテナーが管理する場合は、コンテナー管理パーシスタンス (CMP) と呼びます)。
  • メッセージ駆動型 Bean (MDB)。クライアントにレスポンスを待たせることなく、クライアント・コードからのリクエストに対応します。通常は Java EE 5 のもうひとつのエンタープライズ・アプリケーション技術である JMS (Java Message Service) キューとやりとりをしますが、Java コードで作成されていない非同期クライアントにも他の手段で対応します。

これまでの EJB 開発は複雑で扱いにくかったため、開発者は EJB の実装に必要なすべてのインターフェースとデプロイメント記述子の複雑さを管理するのに、ツールに頼らざるをえないこともよくありました。この場合、ビジネス・ロジック・コードに立ち入ることになるため、特定のクラスを拡張するか、あるいは特定のインターフェースを実装せざるを得ません。また、EJB への単純な参照を取得するのにも、ボイラープレート・コードが大量に必要です。このような問題があることから EJB は開発コミュニティーで悪評を買っていましたが、多くの場合、その悪評は当然のものでした。

EJB プログラミング・モデルの飛躍的改善となる EJB 3.0 は、Java EE 5 開発者の生産性を高める可能性のある最大要因の 1 つです。今や、EJB をアノテーション付きの「POJO (Plain Old Java Object)」にすることができるようになり、特定のクラスを拡張する必要がなくなりました。EJB に必要なのは、開発者が定義するリモート・インターフェースを実装するか、IDE が自動的に作成するリモート・インターフェースを実装することだけです。EJB コンテナーは EJB のアノテーションから必要な情報をすべて抽出できるため、デプロイメント記述子も不要になります。

この記事の「簡単な実例: RideSynergy アプリケーション」セクションに、これらの改善を具体的に説明するサンプル・コードを記載します。さらに踏み込んだ詳細を知りたい方は、「参考文献」にリンクを紹介している 2 つの記事を読んでください。これらの記事に紹介されている例から、最新リリースによって EJB 開発がどれほど改善されたかがよくわかるはずです。

Java Persistence API (JPA 1.0)

JPA では、Java オブジェクトに永続性を持たせるためにオブジェクト・リレーショナル・マッピング (ORM) フレームワークを導入しています。このフレームワークは EJB を念頭に開発されたものですが、あらゆる Java オブジェクトに使用することができます。永続的なオブジェクトとフィールド、そしてマッピング先のデータベース・テーブルと列を指定するにはアノテーションを使います。JPA は SQL と似た機能の豊富な問い合わせ言語をサポートし、この問い合わせ言語によって以下の操作が可能になります。

パラメーター化されたクエリーの定義。このクエリーではパラメーターを、索引番号によって参照する番号付きリストとして、あるいは名前によって参照する名前付きパラメーターとして使用することができます。

JOIN 文を使わずに永続エンティティー間の関係をトラバースするクエリー。ただし、必要に応じて JOIN 文を使用することもできます。

標準的な SQL のような機能を使用した検索基準の構成 (比較演算子、LIKE 文、BETWEEN 文などを使用)、結果セットの処理方法の定義 (DISTINCT、ORDER BY、GROUP BY などの演算子を使用)。

JPA は Java EE プラットフォームに新しい機能をもたらし、これまで開発者独自のパーシスタンス手法やコンテナー固有のパーシスタンス手法につき物だった多くの問題を解消します。記事「EJB 3.0 Java Persistence API を使用したエンタープライズ・アプリケーションの設計」は、JPA の詳細について学ぶ第一歩としてお勧めです。

管理とセキュリティー

Java EE 5 には、以前のバージョンと同じ以下の 3 つの管理/セキュリティー仕様が必要です。

  • Application Deployment。コンポーネントとアプリケーションを Java EE コンテナーにデプロイするための API を規定する仕様です。ツールはこの API にアクセスすれば、Java EE 5 コンテナーを再起動しなくてもコンテナーにコードをデプロイすることができます。IDE では、たいていこの API を使用して開発時のコーディング/テスト/修正のサイクルを短縮化します。
  • Application Management。コンテナーが管理するオブジェクトに必要な属性および操作を指定する仕様です。さまざまな業界標準管理プロトコルと互換性があります。
  • Java ACC (Authorization Contract for Containers)。セキュリティー・ポリシー・プロバイダーのセマンティクス、そしてこの規約内で管理する操作へのアクセスを許可する方法を定義します。この仕様では、コンテナーがデプロイメント・ツールを使って認可の役割の管理を可能にするインターフェースを実装することを規定しています。
  • 上記の Java EE 5 の仕様はいずれも小規模な変更が行われたメンテナンス・リリースで (各仕様とも、J2EE 1.4 で導入されたバージョン 1.0 からバージョン 1.1 へのアップグレード)、この記事ではその詳細については取り上げません。詳細を調べるには、「参考文献」にリンクを記載した Java EE Management and Security Technologies を参照してください。

簡単な実例: RideSynergy アプリケーション

このセクションでは、Java EE 5 の単純化されたプログラミング・モデルが開発者の生産性向上につながる例をいくつか紹介します。紹介するサンプル・アプリケーションには Web サービス・エンドポイントとクライアントが含まれており、このアプリケーションでは EJB をビジネス・ロジックに使用し、JSF を Web フロント・エンドとして使用します。このセクションではまた、Java EE 5 のプログラミング・モデルが、このようなアプリケーションの迅速な開発を可能にする方法についても説明します。

Java EE 5 技術を説明するために、ここでは RideSynergy という架空のサービスのための単純な Web アプリケーションを用います (サンプル・コードについては「ダウンロード」を参照)。RideSynergy は、人々がオンラインで自動車の相乗りを交渉するためのサービスです。開発には NetBeans 5.5 を使用し、Sun Application Server 9.0_01 と WebSphere Application Server (Community Edition) 2.0 の両方でテストしました。

RideSynergy は以下のように機能します。

  • Web ページで相乗りのオファーとリクエストを受け付けます。
  • 相乗りのオファーの場合、オファーと合致するリクエストのリストをユーザーに表示します。
  • 相乗りのリクエストの場合、リクエストと合致するオファーのリストをユーザーに表示します。
  • ユーザーの便宜を考え、相乗りのリクエストまたはオファーの結果と併せて天気予報を表示するオプションがあります。これは、天気によってユーザーの通勤方法が変わる場合があるためです。
  • オファーとリクエストに関する統計を Web サービスとしてサード・パーティー・アプリケーションに提供します。

RideSynergy の訪問者は図 1 のページを使って、相乗りをオファー (offer) するか、リクエスト (request) するかを選択し、出発地と目的地の郵便番号 (ZIP code) を指定して E メール・アドレス (Email) を入力します。このページには、現地の天気予報を表示するオプションもあります。

図 1. RideSynergy のオファー/リクエスト・ページ
RideSynergy のオファー/リクエスト・ページ
RideSynergy のオファー/リクエスト・ページ

オファーがサブミットされた場合、結果ページ (図 2 を参照) にそのオファーと合致する相乗りのリクエストがリストアップされます。リクエストがサブミットされた場合には、そのリクエストと合致するオファーがリストアップされます。天気予報が表示されるのは、オファー/リクエスト・ページの Check weather チェック・ボックスにチェック・マークが入っている場合のみです (実際のアプリケーションでは、5日分の天気予報データが表示されることに注意してください。図 2 では簡潔にするために省略しています)。天気予報データは、http://www.webservicex.net にある公開 Web サービスから取得されます。

図 2. RideSynergy の結果ページ
RideSynergy の結果ページ
RideSynergy の結果ページ

RideSynergy のコードは、Java EE 5 の単純化された Web サービス・プログラミング・モデルを実証するものです。このコードはアノテーションが含まれる Web サービス・エンドポイント定義に JAX-WS を使用し、wsimport 機能によって Web サービス・クライアントを作成します。さらに、このコードには Java EE 5 の単純な EJB プログラミング・モデルと JSF の基本が両方とも示されています。

アノテーション: より少ないコードでより多くの仕事をこなす手段

相乗り利用者の統計を Web サービスとして提供する RideSynergy 機能は、Java EE 5 によって少ないコードで多くの操作が可能になることを実証する例です。この機能は RideStatistics クラスに実装され、Java EE 5 アノテーションのもっとも単純な形を表しています。しかし、単純だからと言ってその威力が足りないというわけではありません。ここに示されたアノテーションが、Java EE 5 でこれらの機能を実装する方法は J2EE 1.4 と比べてどれほど簡単であるかを示しています。

リスト 1 の RideStatistics クラスが実装する Web サービスは、ステートレス RideManagerBean セッション Bean を使って、Web サービス・クライアントが指定する出発地から目的地への郵便番号について RideSynergy ユーザーがオファーしている相乗りの数を検索します。RideManagerRemote インターフェースは、クライアント・コードから利用可能な RideManagerBean での操作、そしてそのコードが同じ JVM で実行されるかどうかを定義します。

リスト 1. RideStatistics Web サービス
package com.ridesynergy;

import java.util.Set;
import javax.ejb.EJB;
import javax.jws.WebService;

/**
 * Web Service that exposes a count of ride offers made to and from specific
 * ZIP codes.
 *
 * @author smoore
 */
@WebService
public class RideStatistics {

   @EJB
   RideManagerRemote rideManager;

  /** Creates a new instance of RideStatistics */
  public RideStatistics() {
  }

   public Integer rideOffersFromZipCode(Integer zipCode) {
      Set<Ride< results = rideManager.findCloseOfferMatches(zipCode, 0);
      return new Integer(results.size());
}

   public Integer rideOffersToZipCode(Integer zipCode) {
      Set<Ride< results = rideManager.findCloseOfferMatches(0, zipCode);
      return new Integer(results.size());
   }
}

リスト 1 には、@WebService と @EJB という 2 つのアノテーションがあります。まずは @EJB アノテーションが依存性を注入して EJB へのアクセスを可能にする仕組みを説明してから、@WebService アノテーションが POJO を本格的な Web サービス・エンドポイントにする仕組みを検討していくことにします。

依存性の注入

J2EE 1.4 での EJB プログラミングに慣れている人がリスト 1 を見ると、EJB の参照を本当にこれほど簡単に取得できるものなのかと思うことでしょう。でも、できるのです。@EJB アノテーションでは、依存性の注入を基にプログラミング・モデルを単純化できるため、EJB の参照の取得はここまで簡単になります。

J2EE 1.4 ではリスト 2 のようなコードが必要になりますが、@EJB アノテーションを使うとこのコードは必要なくなります。

リスト 2. Java EE 5 より前のバージョンの RideManagerBean クライアント
. . .
   Context initial = new InitialContext();
   Context myEnv = (Context) initial.lookup("java:comp/env");
   Object obj = myEnv.lookup("ejb/RideManager");
   RideManagerHome home = (RideManagerHome) PortableRemoteObject.narrow(
         obj, RideManagerRemote.class);
   RideManager manager = home.create();
. . .

Java EE 5 がサポートする EJB 3.0 プログラミング・モデルでは、RideStatistics が JNDI を使って参照を検索しなくても、@EJB アノテーションが RideStatisticsRideManagerRemote に対する依存性を注入してくれます。

さらに、RideManagerRemote が含まれるパッケージへの直接的な依存性も不要になります。import 文を見てみると、RideManagerRemote に対する import 文はありません (もちろん、コンパイルは行います)。つまり、RideManagerRemote は別のパッケージにリファクタリングされる可能性があるため、RideStatistics を更新して再コンパイルする必然性がないというわけです。

アノテーションを使うメリットがあるのは、上記で説明した依存性を注入する側だけではなく、RideManagerRemote の実装を提供し、Java EE 5 コンテナーにその処理内容を指示する実際の EJB にも多くのメリットがあります。この点については、もう少し先で説明します。

複雑なランタイムの振る舞い

Java EE 5 コンテナーにデプロイされると、リスト 1@WebService アノテーションは JAX-WS によって処理され、RideStatistics クラスが 2 つの操作、rideOffersFromZipCoderideOffersFromToZipCode を持つ完全な Web サービス・エンドポイントに変換されます。JAX-WS は Web サービスを提供するために必要なすべての接続を処理します。それには、Web 上の他のアプリケーションがこの Web サービスを検出して使用できるようにするための WSDL (Web Services Description Language) の生成、そしてクライアントの Web サービスに対するリクエストへレスポンスを送る機構の生成も含まれます。

JAX-WS が RideStatistics Web サービスに対して生成する WSDL のデフォルト・ロケーションは http://server:port/ridesynergy2-war/RideStatisticsService?WSDL です。この WSDL を確認するには以下のステップに従ってください。

  1. RideSynergy エンタープライズ・アーカイブ、ridesynergy2.ear をダウンロードして (「ダウンロード」を参照)、Java EE 5 コンテナーにデプロイします。
  2. コンテナーのホスト名とポートをデフォルト・ロケーションのサーバーおよびポートの値として置き換えます。
  3. ロケーションをブラウザーにロードします。

さらに複雑なアノテーション

リスト 1 のアノテーションは単純なものですが、アノテーションでは名前付き要素を使用することも可能です。この名前付き要素はメソッド・パラメーターと似ていますが、それぞれに名前が付けられるため、メソッド・パラメーターとは違ってパラメーターの順序と番号は関係ありません。名前付き要素を使うということは、いわばアノテーションの処理方法を左右するキーと値のペアが含まれるマップをアノテーションに渡すようなものです。

JAX-WS の wsimport が作成する WeatherForecastSoap インターフェースには、名前付き要素を取るアノテーションが含まれています。この WeatherForecastSoap インターフェースはリスト 3 のとおりです。

リスト 3. WeatherForecastSoap インターフェース
. . .  
   @WebMethod(operationName = "GetWeatherByZipCode", 
       action = "http://www.webservicex.net/GetWeatherByZipCode")
   public WeatherForecasts getWeatherByZipCode(
      @WebParam(name = "ZipCode", 
     targetNamespace = "http://www.webservicex.net")
     String zipCode);
. . .

リスト 3 に記載されている getWeatherByZipCode() メソッドには、operationNameaction という名前付き要素を持つ @WebMethod アノテーションがあります。また、getWeatherByZipCode() への zipCode パラメーターにも、nametargetNamespaceという名前付き要素を持つ @WebParam アノテーションがあります (実際のアプリケーションには getWeatherByZipCode() にも別のアノテーションがありますが、ここでは簡潔にするため省略しています)。

アノテーションがどの名前付き要素 (名前要素がある場合) を受け入れるかは、アノテーションを定義するコードが指定します 。詳細は、「参考文献」に記載した入門書「Annotations」へのリンクを参照してください。

ステートレス・セッション Bean の宣言方法

リスト 4 は、リスト 1 で使用した RideManagerRemote インターフェースを実装するステートレス・セッション Bean、RideManagerBean のクラス宣言です。

リスト 4. ステートレス・セッション Bean の宣言
. . .
@Stateless
public class RideManagerBean implements RideManagerRemote {
. . .

J2EE 1.4 の場合、この EJB は SessionBean インターフェースを実装しなければならなかったため、6 つのメソッド実装が必要です。しかし、たいていの場合これらのメソッド実装は最終的には空になります。したがって、インターフェースの条件を満たし、コードがコンパイルできるようにするためだけにしか存在しないメソッドによりコードが雑然としてしまうわけです。EJB 3.0 ではこの乱雑さを排除する方法として、ライフサイクル・アノテーション、@PostConstruct@PreDestroy@PostActivate@PrePassivate を提供しています。これらのアノテーションを必要に応じて、void を返すパラメーターなしの public メソッドに追加することで、ライフサイクル・イベントに対する応答を実装することができます。

デプロイメント記述子の代わりとしてのアノテーション

Java EE 5 でのアノテーションはさらに、以前の Java EE には必要だった構成コードの大部分を不要なものにします。例えばリスト 4@Stateless アノテーションにより、EJB デプロイメント記述子は必要なくなります。EJB デプロイメント記述子とはEJB の詳細をコンテナーに伝える XML 構成ファイルのことで、以前の Java EE プラットフォームでは EJB 2.1 スキーマ準拠の XML ファイルの一部がこれに相当しました。その場合に RideManagerBean とこれに必要なインターフェースの構成をリスト 5 に抜粋します。

リスト 5. Java EE 5 以前のデプロイメント記述子
<display-name>RideManagerJAR</display-name>
<enterprise-beans>
   <session>
      <ejb-name>RideManagerBean</ejb-name>
      <home>com.ridesynergy.RideManagerHome</home>
      <remote>com.ridesynergy.RideManager</remote>
      <ejb-class>com.ridesynergy.RideManagerBean</ejb-class>
      <session-type>Stateless</session-type>
      <transaction-type>Bean</transaction-type>
      <security-identity>
          <use-caller-identity/>
      </security-identity>
   </session>
</enterprise-beans>

Java EE 5 には、以前の EJB デプロイメント記述子との後方互換性があります。必要であれば 2 つの手法を混在させて、レガシー・コードでは記述子を使って EJB を指定する一方、新しい EJB についてはアノテーションで宣言することも可能です。

アノテーションは仕事をやり遂げるために必要なコードの量を減らすだけでなく、Sun のアーキテクトである Graham Hamilton が「truth-in-source-code (ソース・コードの真実性)」と呼ぶ保守上のメリットも実現します (「参考文献」を参照)。クラスに適切にアノテーションが付けられていれば、動作内容を理解するためにソース・コードと構成ファイルの両方を調べる必要はありません。ソース・コードのアノテーションを見れば、定義されている特殊な振る舞いがわかるからです。

Roland Barcia の記事「Java EE 5 の紹介」では、アノテーションが Java EE 5 でのアプリケーション開発を容易にするさまざまな例を取り上げ、コードを中心に検討しています。

妥当なデフォルト

アノテーションを 1 つ追加するだけで RideStatistics を Web サービスにできるということは、もう 1 つの Java EE 5 設計原則をも実証しています。それはつまり、妥当なデフォルトを設定することでプログラミング・モデルを単純化できるということです。

このサンプル・アプリケーションで JAX-WS が前提とするのは、@WebService のアノテーションが付けられたクラス内のあらゆる public メソッドは、メソッドと同じ名前の Web サービス操作に変換されるということです。これらのメソッドの入出力パラメーターが処理される際にも、同じような前提が設定されます。このようなデフォルトの振る舞いが望ましくない場合には、メソッドにアノテーションを付けることで振る舞いをいつでも変更することができます。しかし、たいていは Web サービスで使われる名前と Web サービスを実装するクラスで使われる名前を一致させたいと考えるため、JAX-WS では名前を容易に一致させられるように妥当なデフォルトを設定しています。

まとめ

これまで、Java EE 技術のメリットを受けられたのは、その複雑さと格闘したり、開発ツールを使って管理するのを厭わない人だけでした。Java EE の評判は、これが著しく厄介なプラットフォームであり、大々的なエンタープライズ規模のシステムに強力な機能が必要で、しかも開発上の困難に対処するリソースがある場合にのみ検討すべきだというものでした。

Java EE 5 はこの評判を打ち砕くべく、アノテーションなどの新しい言語機能、妥当なデフォルトといった設計目標を採用し、そしてエンタープライズ・アプリケーション開発を身近にする強力なプラットフォームを実現するための単純なプログラミング・モデルに重点を置いています。プログラミング・モデルの単純化により、開発会社が不要な複雑さの管理にサード・パーティー製のツールに頼ることも少なくなります。これは、費用を負担する人々にとっては、大幅に少ない費用で今まで以上に強力なエンタープライズ・アプリケーションを開発できるという結果になります。一方、開発者にとっての結果としては、プラットフォームと奮闘する時間が短くなる一方、プラットフォームをベースに素早く開発した機能で一層上司を感心させられることになります。

今まで Java EE 技術を避けていた開発会社は是非、この技術を新しい目で見直してみてください。そして既存の J2EE アプリケーションの開発や保守に携わる人は Java EE 5 を調べることをお勧めします。そこには、開発や保守作業を楽にするさまざまな手段が見つかるはずです。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Java technology
ArticleID=280546
ArticleTitle=Java EE 5: その威力と生産性、そして軽減された複雑さ
publish-date=11292007