EJB の提唱シリーズの各コラムでは、興味深い設計問題に対するソリューションを推奨する上で実際の顧客と開発者との間で交換される、典型的なやり取りの要点を紹介しています。顧客を特定できるような詳細部分はぼかし、また「革新的な」アーキテクチャーや独自アーキテクチャーは紹介しません。このシリーズについて詳しくは、「 Introducing the EJB Advocate 」を参照してください。
EJB 提唱者殿
私は SOA (Service Oriented Architecture) がもてはやされる現状に戸惑っていますが、あなたはよく理解されているようです。
例えば、「Is it ever best to use EJB components without facades in service oriented architectures (SOA でファサードなしに EJB コンポーネントを使うことが本当にベストなのか)」の中では、EJB コンポーネントの設計において、EJB コンポーネントを「サービス指向」にするために従うべきベスト・プラクティスとして、粒度を荒く、ステートレストするように解説されています。
そこで解説されている原則は、私達のように分散オブジェクト技術 (CORBA や EJB) を使ったアプリケーションの構築に成功した者にとっては特別新しいものではありません。私達は今までもずっと、「サービス指向」であったと思います。
確かに、「サービス指向」アーキテクチャーと言う方が「分散オブジェクト」アーキテクチャーと言うよりも略語としては的確かもしれませんが、それを除けば、『SOA のどこが新しいのか』という本質的な疑問を私は抱いています。特に、EJB コンポーネントで何でもできるにもかかわらず、なぜ新しい Service Component Architecture や Service Data Object の仕様を考慮すべきなのでしょう。
署名
『SOA が何だ』より
親愛なる『SOA が何だ』殿
私は EJB 提唱者なので、私がこう言うと驚かれるかもしれませんが、EJB コンポーネントを使えば何から何までサーバーサイドで Java™ でできるからといって、必ずそうすべきだ、ということにはなりません。クライアントサイドで見られた Java サーブレットの進化と同じく、サーバーサイドで自然な技術進化が起きている、というのが私の受け取り方です。
忘れてしまった人もいるかもしれませんが、Java サーブレットは、Microsoft® の ISAPI (Internet Server API) など特定の Web サーバーに関する独自のJava API を統一するための、標準 Java ベースのコンポーネントとして導入されました。Java プログラマーは Java サーブレットのおかげで、さまざまなベンダーのさまざまな Web サーバーで実行できる、動的な Web ページ生成用のコンポーネントを開発できるようになりました。
最も一般的に使われるコンポーネントは HttpServlet です。HttpServlet は、HTTP リクエスト・ストリームからの入力と HTTP レスポンス・ストリームへの出力のマッピングの詳細をすべて処理してくれるため、プログラマーはそうした詳細から解放され、アプリケーションのフロー・ロジックに集中することができます。
これが非常に便利であったため、ユーザーは間もなく、HTML を Java コードで生成するのは面倒だと思い始めました。例えば下記は、単純な動的な「Hello world」を生成する HttpServlet doGet() メソッドのスニペットです。
String name = request.getAttribute("name");
PrintWriter pw = request.getPrintWriter();
pw.println("<HTML>");
pw.println("<BODY>");
pw.println("<P>Hello " + name + "!</P>");
pw.println("</BODY>");
pw.println("</HTML>"); |
そしてすぐにさまざまな「テンプレート」言語が登場し始めました。テンプレート言語を使えば HTML の中に Java コードを埋め込むことができ、プログラミング・モデルを、より一層 WYSIWYG (つまり宣言型) にすることができました。こうした手法の標準化から JSP (Java Server Page) 仕様が生まれました。JSP では、Java の「スクリプトレット」(<%...%>) と「式」(<%=…%>) を HTML と混在させることができます。例えば下記は、同じ「Hello world」を表示する、JSP のスニペットです。
<% String name = request.getAttribute("name"); %>
<HTML>
<BODY>
<P>Hello <%=name%>!</P>
</BODY>
</HTML>" |
括弧や引用符、セミコロンなどを無くしただけで、Web アプリケーションのプログラマーは何千ものバグを未然に防ぐことができました。しかも、HttpServlet コンポーネントをコンパイルしてパッケージ化し、デプロイする必要がなくなったため、(バグの修正かどうかによらず) 変更に要する時間が大幅に削減されました。
さらに重要なこととして、JSP によってアーキテクチャーに変化が生まれ、ビューを描画するためのコンサーンとデータを取得するためのコンサーンとが分離されるようになりました。これにより急に、Web ページの設計者やアプリケーション・プログラマーは、お互いの領域に踏み込むことなく協力作業が行えるようになり、それぞれの役割に適した言語やスタイルで、独自のコンポーネントを開発できるようになりました。
余談ですが、EJB 仕様は、さらにコンサーンを分離するために、ほぼ同時期に生まれました。EJB コンポーネントが追加されたことによって、Web アプリケーションのための、真の Model-View-Controller アーキテクチャーが実現されたのです (このアーキテクチャーでは、モデルは EJB コンポーネントによって、ビューは JSP によって、そしてコントローラーは HttpServlet によってカプセル化されます)。
残念なことに、本当に有用なものを描画するためには、Java スクリプトレットと Java 式、そして静的な HTML という間のやり取りが、非常に複雑になります。例えば、下記は注文の ID と状態のリストを生成するためのスニペットです。
<%
OrderStatus orderStatus = (OrderStatus)request.getAttribute(
"OrderStatus"
);
OrderData d[] = orderStatus.orders;
int orderID = 0;
String status = null;
for (int i=0 ; i < d.length; i++)
{
orderID = d[i].orderID;
status = d[i].status;
%>
<P>Order Id =<%=orderID%> Status =<%=status%></P>
<% } %> |
ループを開始するためのスクリプトレットは少し複雑です。ループを終了するスクリプトレットは非常に単純ですが、忘れられがちです (あるいは誤った場所に置かれがちです)。JSP を編集する際 (Java IDE で「純粋な」HttpServlet を編集する場合と同様に) に、こうした間違いや他の一般的なバグを捉えるツールはありません。
簡単に言えば、普通の Web ページ設計者、特にプログラミングの訓練をしていない Web ページ設計者に対して、 Java スクリプトレットと Java 式を適切に使うように求めるのは無理、という問題は残ったままです。
Java プログラミングを最小限にとどめ、さらには無くしてしまうために、カスタム JSP タグの概念が生まれ、標準化されました。例えば IBM の Software Services for WebSphere では、ネスト構造をまたがった繰り返しが可能なカスタム・タグをいくつか開発しました。こうしたタグは、ベースとなる JSP タグ・ライブラリーの一部として提供される USEBEAN タグや GETPROPERTY タグと一緒に使うことができ、これによってロジックが下記のように非常に単純になります。
<JSP:USEBEAN ID="OrderStatus" CLASS="com.onlinemall.data.OrderStatusData" SCOPE="request"/> <SW296:INDEXEDBEANPROPERTY BEAN="OrderStatus" PROPERTY="orders" VAR="order" TYPE="com.onlinemall.data.OrderData"> <P>Order ID=<JSP:GETPROPERTY NAME="order" PROPERTY="orderID"/> Status=<JSP:GETPROPERTY NAME="order" PROPERTY="status"/></P> </SW296:INDEXEDBEANPROPERTY> |
やがて間もなく、HttpServlet を書かなくて済む、Struts のようなフレームワークが登場しました。Struts には、フォーム処理のためのカスタム・タグが豊富に含まれているだけではなく、宣言型でページを構成するための、「タイル」と呼ばれる概念も含まれています。タイルの重要な機能として、ページの再構成を、基礎となるコード・コンポーネントを変更せずに非常に容易に行えることがあげられます。Struts を基にして、コンポーネントから UI を宣言型で組み立てる概念を標準化した、JSF (Java Server Faces) が生まれました。Roland Barcia による素晴らしい記事では、JSF と Struts とを対照しながら詳述していますので参照してください。
クライアントサイドでの、Java サーブレットから JSP、カスタム・タグ・フレームワーク、そして JSF、という進化は、コンパイルが必要な手続き型でプログラムされたコンポーネントから、インタープリターで解釈可能な (あるいは少なくとも実行時コンパイルの)、宣言型で構成されたコンポーネントに向かうための、順を追ったステップと言うことができます。SCA (Service Component Architecture) も、同じような進化と考えることができます。つまり SCA によって、サーバーサイド・コンポーネントを宣言型で組み立て、アプリケーションとして構成できるのです。
developerWorks にある、Service Component Architecture や Service Data Object に関する他の何本かの記事に目を通した方は、SCA のコンポーネントを説明する、下記のような図を見たことがあると思います。
図 1. SCA コンポーネントの例
SCA コンポーネントと EJB コンポーネントとを比較する際に考慮すべき重要な点として、次の 3 つがあります。
-
合成: EJB コンポーネントの場合、実装に利用できる言語は Java のみです。そのため、あらゆるサービスを合成して大きな構成とするための作業は、Java によって手続き型で行われます。SCA は実装言語として、Java だけではなく BPEL (Business Process Execution Language、ステート・マシンやビジネス・ルール、ヒューマン・タスクなどの概念を処理できるように拡張されています) もサポートしています。
-
呼び出し: ステートレス・セッション Bean の使い方は、ステートフル・セッション Bean やエンティティー Bean、Custom Entity Home Method あるいはメッセージ駆動型 Bean などの使い方とは異なります。具体的には、それぞれのコンポーネント・タイプは、メソッドを探し、呼び出すために別々の方法を持っています。一方 SCA コンポーネントの場合は、実装タイプにかかわらず、クライアントに対して共通の呼び出しモデルを使うことができます。
-
データ: エンティティー EJB コンポーネントは、コンテナーのスコープやトランザクション境界の外でシリアルライズして効率的に使うようには作られていません。そのため、その隙間を埋めるためにデータ転送オブジェクト (Data Transfer Object) が進化しました。SDO コンポーネントは、スコープとは無関係に、コンポーネント間でのデータ・フローを一般的に抽象化しています。
合成や呼び出し、そしてデータに関して、選択が単純化されたことによって、SCA で可能なサービスからアプリケーションを宣言型で構成するという進化が実現されました。これはちょうど、JSP とカスタム・タグによって UI を宣言型で構成する方向への流れが生まれたのと同じです。
つまり、なぜ SOA を考慮すべきなのかを要約すれば、ビジネス・アナリストは SOA によって、やがてプログラマーによる最低限のサポートでアプリケーションを構成できるようになるからです。
OK then,
EJB 提唱者より
EJB 提唱者殿
私は今まで、宣言型言語に向かうというクライアントサイドでの傾向が、サーバーサイドにも当てはまると考えたことはありませんでした。あなたの回答からすると、そもそも私は EJB コンポーネントを使うべきなのでしょうか。
署名
『SOA に困惑』より
EJB コンポーネントは DNA のようなもの、つまり進化の構成ブロックです。
親愛なる『SOA に困惑』殿
私が先ほど要約した中で重要な意味を持つ言葉は、「やがて」と「最低限」です。
「やがて」というのは、BPEL 用のランタイム・インタープリターがエンタープライズ・アプリケーションのあらゆる側面に必要とされる機能やパフォーマンスを満足するまでには、しばらく時間がかかる、という意味です。例えば、「マイクロ・フロー」(1 つの作業単位を実行するためのロジック) の方が、EJB コンポーネントとしては優れたパフォーマンスを示すかもしれません。
「最低限」というのは、たとえ BPEL 標準が拡張され、ビジネス・アナリストがステート・マシンやヒューマン・タスク、ビジネス・ルールなどの宣言型概念を使ってロジックを規定できるようになったとしても、手続き型を使った方がうまく規定できるようなロジック・パターンが必ずいくつかある、という意味です。「手続き型」のタグ、あるいはビジュアル・プログラミング言語を作ることは可能ですが、そうしたものは Java ほど単純ではなく、追加で入力しなければならないタグ構文やコンポーネント間に描画する線などのすべてを考えると、おそらくもっと複雑になります。
要約すると、EJB コンポーネントを手動でコーディングする必要は少なくなるかもしれませんが、複雑で高品質のエンタープライズ・アプリケーションでは、いくつかの EJB コンポーネントは相変わらず必要とされるはずです。こうした理由から、EJB コンポーネントは、サーバー・サイド・コンポーネントを拡張する際のベースと、構成ブロックと考えるべきなのです。
あなたがこの返事を読んだら、『SOA ハッピー』として署名してくれることを祈っています。
OK then,
EJB 提唱者より
- 「Java Platform, Enterprise Edition (JEE) 仕様 (これまでの J2EE)」を見てください。エンタープライズ用 Java プラットフォームの中心概念を特定のバージョンから切り離すために、「2」がなくなりました。
- 「Enterprise Java Programming with IBM WebSphere, Second Edition」を読んでください。著者は Kyle Brown と Gary Craig、Greg Hester、Russell Stinehour、W. David Pitt、Mark Weitzel、JimAmsden、Peter M. Jakab、Daniel Berg であり、また Martin Fowler が前書きを書いています。
- Geoffrey Hambrick 著による、「The EJB Advocate: Is it ever best to use EJB components without facades in service oriented architectures?」を読んでください。
-
JavaServer Faces (JSF) vs. Struts: A brief comparison を見てください。
-
Service Component Architecture を見てください。
-
Introduction to Service Data Objects を見てください。

Geoff Hambrick はテキサス州の Round Rock (Austin 近郊) に住み、IBM Software Services for WebSphere Enablement Team の中心コンサルタントです。このチームは主に、技術的に掘り下げた要点説明や短期間の概念検証作業などをとおして、販売前のプロセスをサポートしています。彼は IBM WebSphere Application Server 上でホストされる J2EE アプリケーションを開発するためのベスト・プラクティスを作成し、周知させたことに対して、2004 年の 3 月に IBM Distinguished Engineer に指名されました。