Geronimo への転向: 統合パッケージを使用する: GlassFish JSTL 1.2 と Apache Geronimo 2.0

JSTL と Geronimo 2.0 によって今までになく広がる、Java Web アプリケーションを構築する際の選択肢

Apache Geronimo チームが、新しい話題の Java EE (Java Platform, Enterprise Edition) 5.0 仕様の実装に成功しました。Java EE 5 で注目に値する特徴の 1 つは、新規 JSTL (Java Standard Tag Library) 仕様です。JSTL 1.2 の鍵である統一式言語により、JSF (JavaServer Faces) と併せてJSTL 選り抜きの機能を使用できるようになります。連載「Geronimo への転向」では今回、Java Web 技術の歴史を振り返って JSTL 1.2 の重要性を説明し、Geronimo チームが JSTL 1.2 サポートを Geronimo に追加するために、どのように GlassFish JSTL 1.2 の実装を活用したかを紹介します。

Michael Galpin (mike.sr@gmail.com), Developer, MichaelDKelly.com

Michael Galpin は 1998年からプロとして Java ソフトウェアを開発しています。現在は、カリフォルニア州 Mountain Viewにある新興企業、Adomo, Inc. に勤務しています。California Institute of Technology で数学の学位を取得しました。



2007年 8月 28日

Java Web 技術の進化

Enterprise Java 言語には常に Web 技術が伴ってきました。Web 技術の進化の過程は、サーブレットを起点としています。

サーブレット

サーブレットは当初、HTTP リクエストに応答するために使用されていました。その当時、サーブレットを作成するのが通常いかに厄介な作業であったかは、リスト 1 の例を見ればわかります。

サーブレットによる HTML の生成
     protected void doGet(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException {
          ServletOutputStream out = response.getOutputStream();
          out.println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 
Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">");
          out.println("<html xmlns=\"http://www.w3.org/1999/xhtml\">");
          out.println("<head>");
          out.println("<meta http-equiv=\"Content-Type\" content=\"text/html; 
charset=ISO-8859-1\" />");
          out.println("<title>All Users</title>");
          out.println("</head>");
          out.println("<body>");
          out.println("     <table>");
          out.println("          <tr>");
          out.println("               <td>UserID</td>");
          out.println("               <td>UserName</td>");
          out.println("               <td>Name</td>");
          out.println("          </tr>");

          UserDao dao = new UserDao();
          List users = dao.getAllUsers();
          for (int i=0;i<users.size();i++){
               User user = (User) users.get(i);
               out.println("          <tr>");
               out.println("               <td>"+user.getId()+"</td>");
               out.println("               <td>"+user.getUserName()+"</td>");
               out.println("               <td>"+user.getFirstName()+' 
'+user.getLastName()+"</td>");
               out.println("          </tr>");
          }
          out.println("     </table>");
          out.println("</body>");
          out.println("</html>");
     }

サーブレットでは大量の HTML (一例) を Java コードに埋め込む必要がありました。サーブレットを開発するより難しかったのは、唯一、サーブレットを維持することです。例えば、リスト 1 のコードで表に枠を持たせるとします。その場合、Java コードを変更してからサーブレットを再コンパイルしなければなりませんでしたが、幸いにもこの後すぐ、サーブレットは JSP (JavaServer Pages) 技術によって強化されることになります。

JSP (JavaServer Pages)

Java サーブレットを強化したのは JSP 技術です。JSP コンポーネントはさまざまな改善をサーブレットにもたらしました。その 1 つが、ネイティブ・マークアップと Java コードを混在できるようにしたことです。リスト 2 は、リスト 1 のサーブレットと同じものを JSP コンポーネントとして記述したものです。

JSP 1.0 バージョン
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="org.developerworks.*" %>
<%@ page import="java.util.List" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
     <table>
          <tr>
               <td>UserID</td>
               <td>UserName</td>
               <td>Name</td>
          </tr>
          <%
               UserDao dao = new UserDao();
               List users = dao.getAllUsers();
               for (int i=0;i<users.size();i++){
                    User user = (User) users.get(i);
          %>
          <tr>
               <td><%= user.getId() %></td>
               <td><%= user.getUserName() %></td>
               <td><%= user.getFirstName() %> <%= user.getLastName() 
                 %></td>
          </tr>
          <%
               }
          %>
          </c:forEach>
     </table>
</body>
</html>

リスト 2 の内容がサーブレットに比べて大幅な改善であることは明らかです。JSP コンポーネントは以前と同じくサーブレットにコンパイルされていますが、コンパイルを行うのはサーブレット・コンテナーです (または、ビルドの一部として行われる場合もあります)。そのため、JSP コンポーネントはサーブレットと同じパフォーマンスを実現することが可能でした。PHP 構文は ASP (Active Server Page) および PHP ページと同様ですが、サーブレットにコンパイルすることで、JSP コンポーネントのパフォーマンスを他の技術より格段に優れたものにしています。


JSP Model 2

リスト 2 の JSP コードには、まだ大きな問題が残されています。それは、JSP コードがスクリプトレットを使用していることです。スクリプトレットとは短い Java コードのことですが、スクリプトレットの使用には設計および実用面の両方で問題がありました。JSP コンポーネントがビジネス・ロジック (ユーザー・リストの取得) をプレゼンテーションと混在させてしまうからです。この問題を解決するために進化したのが JSP Model 2 アーキテクチャーです。このアーキテクチャーでは、JSP コンポーネントと併せてサーブレットを使用することができます。リスト 3 を見てください。

Model 2 スタイルのサーブレット
    protected void doGet(HttpServletRequest request, HttpServletResponse response) 
throws ServletException, IOException {
        UserDao dao = new UserDao();
        List users = dao.getAllUsers();
        request.setAttribute("users", users);
        request.getRequestDispatcher("/user.jsp").forward(request, response);
    }

上記では、サーブレットがリクエストを処理してからビジネス・ロジックを実行し、それから結果を HttpServletRequest オブジェクトに保管して JSP コンポーネントに転送できるようになっています。これにより、リスト 4 のように JSP コンポーネントを単純化することができます。

Model 2 スタイルの JSP コンポーネント
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ page import="org.developerworks.*" %>
<%@ page import="java.util.List" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"  
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
    <table>
        <tr>
            <td>UserID</td>
            <td>UserName</td>
            <td>Name</td>
        </tr>
        <%
            List users = (List) request.getAttribute("users");
            for (int i=0;i<users.size();i++){
                User user = (User) users.get(i);
        %>
        <tr>
            <td><%= user.getId() %></td>
            <td><%= user.getUserName() %></td>
            <td><%= user.getFirstName() %> <%= user.getLastName() 
   %></td>
        </tr>
        <%
            }
        %>
        </c:forEach>
    </table>
</body>
</html>

これでアーキテクチャーの問題は解決しますが、実用面での問題がまだ残っています。Java コードと HTML を混在させると、HTML をそれほどよく知らない Java 開発者と Java 言語をよく知らない Web 設計者の双方にとって JSP コンポーネントを扱うのが難しくなるという問題です。

JSTL (JavaServer Pages Standard Tag Library)

そこで JSP 技術の目標となったのが、JSP コンポーネントをクリーンアップし、すべての Java スクリプトレットを取り除くことでした。そしてこの目標を追求した結果、完成したのが JSTL です。JSTL が導入した HTML スタイルのタグによって、Java オブジェクトにアクセスし、コレクションの反復処理、条件付きロジック、テキストのフォーマット設定をはじめとする多くの Java プログラム言語の構成要素を実行できるようになりました。リスト 5 は、JSTL によって進化した JSP コンポーネントです。

JSTL による JSP
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
     <table>
          <tr>
               <td>UserID</td>
               <td>UserName</td>
               <td>Name</td>
          </tr>
          <c:forEach items="${users}" var="user">
          <tr>
               <td><c:out value="${user.id}"/></td>
               <td><c:out value="${user.userName}"/></td>
               <td><c:out value="${user.firstName}"/> <c:out
 value="${user.lastName}"/></td>
          </tr>
          </c:forEach>
     </table>
</body>
</html>

<c:forEach> タグでユーザー・リストの繰り返し処理を可能にし、<c:out> タグで Java オブジェクトにアクセスし、そのデータを出力できるようにしています。

タグ内で使われている ${users}${user.id} などの式を解釈するのは、JSTL EL (Expression Language) です。例えば、EL は ${users} ストリングを解釈し、pageContextrequestsession、そして servlet (アプリケーション) コンテキストなどのアクセス可能なさまざまなオブジェクトで users 属性を探します。JSP コンポーネントはさらに進化し、JSTL タグの外側でも EL を使用できるようにしました。リスト 6 は、この進化による JSP コンポーネントです。

JSTL と EL を使用した JSP
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
     <table>
          <tr>
               <td>UserID</td>
               <td>UserName</td>
               <td>Name</td>
          </tr>
          <c:forEach items="${users}" var="user">
          <tr>
               <td>${user.id}</td>
               <td>${user.userName}</td>
               <td>${user.firstName} ${user.lastName}</td>
          </tr>
          </c:forEach>
     </table>
</body>
</html>

上記は JSTL の最新の形式と JSP 2.0 仕様において初めて登場した EL です。この JSTL と EL の組み合わせを Model 2 アーキテクチャー (多くの場合、Apache Struts などの各種 UI フレームワークによって実装) と結合すると、基本的に Java に縛られない JSP コンポーネントを作成することが可能になります。これで、Java 以外のプログラマーでも JSP コンポーネントを操作できるようになり、Java 開発者がアプリケーションのビジネス・ロジックの実装に専念することができます。

JavaServer Faces 技術

ただし、JSP 技術だけが Enterprise Java アーキテクチャーを構成する Web 技術ではありません。JSP 2.0 仕様の登場からまもなくして、JSF 技術も登場しました。JSF はコンポーネント・アーキテクチャーとなるように設計された技術です。JSF では、Web ページ上のオブジェクトはライフ・サイクルを持ち、Java オブジェクトがバインドされたコンポーネントとして見なされます。したがって、この記事の JSP の例では JSF を使用すれば Java オブジェクトをビュー・コンポーネントに直接バインドすることができます。その結果、JSP コンポーネントはリスト 7 のようになります。

JSF を使用した JSP
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
<%@ taglib uri="http:.//java.sun.com/jsf/core" prefix="f" %> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<title>All Users</title>
</head>
<body>
     <f:view>
          <h:dataTable id="users" value="#{UserBean.users}" var="user">   
            <h:column>
              <f:facet name="header">UserID</f:facet>
               <h:outputText value="#{user.id}"/>
            </h:column>
            <h:column>
              <f:facet name="header">UserName</f:facet>
               <h:outputText value="#{user.userName}"/>
            </h:column>
            <h:column>
              <f:facet name="header">Name</f:facet>
               <h:outputText value="#{user.firstName}"/> <h:outputText 
value="#{user.lastName}"/>
            </h:column>
          </h:dataTable>           
     </f:view>
</body>
</html>

dataTable コンポーネントを Java オブジェクトにバインドする方法に注目してください。バインドしてしまえば、後は表の列を定義するだけで、このコンポーネントが行を繰り返し処理することを認識します。ここで前提となるのは、使用しているデータで管理対象のバッキング Bean (UserBean) が作成済みであることです。dataTable コンポーネントはHTML を自動的に作成するので、表の作成するために HTML を指定する必要はありません。これが、JSF の利点の 1 つです。


JSF と JSP 1.2

JSF は常に JSP 技術を利用してきましたが、JSF が導入された時点で最も汎用的に使われていた JSP 技術のバージョンは JSP 1.2 です。つまり、JSF は JSP 1.2 をベースとしていたため、JSTL と EL をサポートしていませんでした。お気付きだったかもしれませんが、<h:dataTable> タグと <h:outputText> タグには value 属性があります。これらのタグの見た目は JSTL が使用する EL に似ていますが、JSF 1.0 では文字どおり表面的に似ているだけで、JSF には JSTL が導入した EL と同じように機能する独自の EL があります。これはその後、JSP 技術固有の EL となりましたが、JSF EL は JSTL EL とは互換しませんでした。ただし、それはもう過去の話です。

統一式言語

Java EE 5 のキー・ポイントとして挙げられるのは、統一式言語です。そのため JSTL が使用する EL と JSF が使用する EL はマージされました。リスト 8 に示すように今や、JSTL と JSF は混在させられるようになっています。

JSF と JSTL の混在
     <f:view>
          <c:forEach items="${UserBean.groups}" var="group">
               ${group.groupName}
               <h:dataTable id="#{group.groupId}" value="#{group.users}" 
   var="user"> 
                 <h:column>
                   <f:facet name="header">UserID</f:facet>
                    ${user.id}
                 </h:column>
                 <h:column>
                   <f:facet name="header">UserName</f:facet>
                    ${user.userName}
                 </h:column>
                 <h:column>
                   <f:facet name="header">Name</f:facet>
                    ${user.firstName} ${user.lastName}"
                 </h:column>
               </h:dataTable>           
          </c:forEach>
     </f:view>

リスト 8 の例では、まず JSTL によって繰り返し処理される複数のグループがあります。それからグループごとに表示テーブルを作成し、グループに含まれるユーザーをリストします。注目すべき点は、JSTL タグ (<c:forEach>) と JSF コンポーネント (<h:dataTable>) それぞれのデータを参照するための異なる EL が、JSP コンポーネント内で直接 EL 式として使用されていることです。 このように JSTL と JSF の EL を混在できるため、両方の長所が生かされます。

Java EE 5 の一部としての EL

Java EE 5 の EL には、もう 1 つ大幅な変更があります。J2EE 1.4 仕様では JSTL 実装が要件となっていなかったため、Web アプリケーションでどの JSTL 実装を使用するかは、そのアプリケーションの開発者が選ぶことができました。もちろん、アプリケーションで JSF 実装だけを使用するという選択肢もありました。

Java EE 5 仕様では JSTL 実装が要件となっています。

そのため、Web アプリケーション開発者はどの実装をアプリケーションに組み込むかという心配から解放され、迷わず JSTL を使用できるようになりました。その上、JSF の機能も利用することができます。これは、Java EE 5 仕様の一部である統一式言語ならではの利点です。


Geronimo と GlassFish JSTL

前のセクションで説明したように、以前は Web アプリケーション開発者が JSTL 技術を組み込むかどうかを選択できました。JSTL 技術を組み込むことにした場合、アプリケーションにどの JSTL 実装を組み込むかは Web アプリケーション開発者次第です。開発者に用意された JSTL 実装の選択肢はさまざまでした。

Java EE 5 では、アプリケーション・サーバーに JSTL が装備されています。そのため、Java EE 5 仕様の実装にはいずれも JSTL 実装を組み込なければなりません。Apache Geronimo の開発者たちも、Java EE 5 実装 (Geronimo 2.0) に取り掛かる際に JSTL 実装を組み込む必要に迫られました。

しかし、Geronimo チームは既存の実装をどれも選択できませんでした。統一式言語は JSTL 実装の主要な要件でしたが、JSTL 実装の多くは JSF と連動するようには設計されていなかったためです。幸い、Geronimo チームは自分たちで JSTL と統一式言語を実装しなくても済みました。彼らには、Sun の GlassFish を利用するという手があったのです。

GlassFish に馴染みのない読者のために説明しておくと、これは Sun による Java EE 5 仕様のリファレンス実装です。オープン・ソースのアプリケーションである GlassFish は、Sun の CDDL (Common Development and Distribution License) および GNU GPL (General Public License) の両方により使用が許諾されています。Sun では常に JSF のリファレンス実装を提供してきたため、統一式言語を組み込んだ JSTL のリファレンス実装の提供にも素早く対応しました。GlassFish に備わっているオープン・ソースの性質により、Geronimo チームは GlassFish を活用して Geronimo 2.0 に GlassFish JSTL 実装を組み込むことができたというわけです。GlassFish は、Geronimo の最初のマイルストーン・リリース、Geronimo 2.0-M1 に組み込まれました。

ライセンス交付についての考慮事項

GlassFish は CDDL と GPL の両方によって使用が許諾されているので、Geronimo に組み込むことができます。ただし、そのライセンスは他の Geronimo のような Apache スタイルのライセンスではないため、Geronimo チームにはいくつかの制約が課せられました。

基本的に Geronimo は GlassFish JSTL を組み込んでいますが、そのソース・コードについては別です。さらに、Geronimo チームは明らかに GlassFish JSTL に貢献しているとは言え、ソース・コードを変更して新しいバイナリーを Geronimo にパッケージ化することはできません。

Geronimo の最大の利点の 1 つは、自分でコードを変更してカスタマイズした Geronimo バージョンを配布できるということですが、JSTL 実装の場合は完全に例外です。ソース・コードは Geronimo に組み込まれておらず、そのライセンス交付によってカスタマイズ・バージョンの配布は制約されています。例えば GlassFish のソースを変更した場合、その変更は GlassFish と同じライセンスで利用できるようにしなければなりません。


まとめ

Java 技術における Web 技術の進化は、長年にわたって大きな利益を開発者に与えてきました。最新の進化である統一式言語は、JSTL 技術と JSF 技術を一緒に使えるようにすることで、開発者にとってさらに大きな利益となることが期待されます。統一式言語は現在、Java EE 5 仕様の重要な部分となっているため、Geronimo 2.0 でも同じく重要な部分となります。Geronimo は Java EE 5 仕様を実装するだけでなく、この仕様のリファレンス実装を使用することによって、またもや開発者を支援することになりました。GlassFish JSTL と Geronimo 2.0 のおかげで、Java Web アプリケーションを構築する開発者に、かつてないほど豊富な選択肢が広がっています。

参考文献

学ぶために

製品や技術を入手するために

  • Apache Geronimo の最新バージョンをダウンロードしてください。
  • IBM WebSphere® Application Server Community Editionの無料コピーをダウンロードしてください。これは Apache Geronimo オープン・ソース技術の上に構築された軽量の J2EE アプリケーション・サーバーであり、皆さんの開発やデプロイ作業を加速するために役立つはずです。
  • IBM ソフトウェアの試用版を使用して、次のオープン・ソース開発プロジェクトを革新してください。ダウンロード、あるいは DVD で入手できます。

議論するために

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Open source, Java technology, WebSphere
ArticleID=259405
ArticleTitle=Geronimo への転向: 統合パッケージを使用する: GlassFish JSTL 1.2 と Apache Geronimo 2.0
publish-date=08282007