緒言

jspbp は Java 用の Web アプリケーションフレームワークである。

あなたの反応:「なに、新作の Webアプリケーションフレームワーク だって? それもJava用? おいおい、このプログラマは正気じゃないぞ。 この世にはもう百個くらいWebアプリケーションフレームワークがあって、なかでもJava用が一番多くて、 そのうちのいくつかは何十人ものフルタイムのプログラマ(金持ちの大企業に雇われている) と何トンものツールに支えられていて、おまけに今の流行りは Ruby on Rails だ。 なにに手を出すにしても、これほど最悪のことなんか、ほかに思いつくことさえできやしない!」

オーケー、そういうことだ。私は喧嘩を売っている。この世にごまんとあるJava用のWebアプリケーションフレームワークは、 すべて屑だと公言している。その設計者たちが全員間抜けで、私のほうが賢いのだと、そう言っている。

私が調べ物をしなかったとか、学習にかかる時間を惜しんだとは思ってほしくない。私はJSF 1.1 と 1.2 の違いを知っていて、それが今更どうにもならない設計ミスに対する、愛想笑いと同じくらい無意味な弥縫策であることを見てとっている。

あなたの反応:「面白い、お前の馬鹿さ加減を味見してやるか。どんなツールがある? ドキュメントは?」

ない。ツールもドキュメントもない。あるのはサンプルの jspbp-helloworld と、 製品の Yamibou だけだ。

何十人ものフルタイムのプログラマと正面から張り合うほど私は間抜けではない。私はひとり、たったひとりだ。 ツールやドキュメントの物量でかなうわけがない。だからそんなものは作らない。

jspbp の戦略は以下の2点に要約できる。

  • ユーザがすでに知っているであろう一般的な知識に依存する
  • 機能とコードを最小限に絞り込む

一般的な知識とは、

  • サーブレット
  • JSTL
  • Maven

である。jspbp はこれらの技術を利用して動作する。jspbp では、これらの知識がすべて活用できる、というより必要になる。

jspbp のボリュームは、

  • Java ソースコードの行数(空行を含む): 3433行
  • ユーザが接する class / interface の数: 5個
  • JSP タグの数: 4 個

である。

どこかの馬鹿:「プログラマとデザイナーの分業を――」

うん? 口からクソを漏らしてるのはどこの馬鹿だ? そういう機能はアプリケーションレベルのもので、フレームワークが提供するものではない。 それがわからない馬鹿どもが、クソも味噌もいっしょにしてWebアプリケーションフレームワークを設計して、 そこに何トンものツールを積むと、そびえたつクソのできあがりだ。

アーキテクチャ

JSTL には組み込みの暗黙オブジェクトがある。sessionScope や param などだ。jspbp は、サーブレットフィルタを用いて、 behind という名前のオブジェクトを提供する。behind は暗黙オブジェクトと同様、JSTL の式言語に用いることができる。

その behind のクラスはどのように決定され、どんなライフサイクルを持つのか? クラス決定は、リクエストのサーブレットパスをもとに行われる。サーブレットパスが /foo/bar.jsp であるなら、 XXXXX.foo.Bar が完全修飾クラス名となる。なお、XXXXX の部分は web.xml で指定する(jspbp-helloworld を参照)。 behind は原則としてリクエストのたびに new される(例外は後述)。なおコンストラクタには引数なしのものを用いる。

リクエストのパラメータ

jspbp は behind を new したあと、リクエストのパラメータを与える。リクエストのパラメータは「名前:値」のペアの配列だが、 これを behind のプロパティとしてコピーする。同一の名前が複数ある場合は、パラメータ名の末尾に List を加えたものがプロパティ名となる。 パラメータ名が behind のプロパティ名にない場合は、単にそのパラメータを無視する。なお multipart/form-data の場合も同様にコピーする。

jspbp は behind にパラメータをコピーしたあと、behind の beforeGet ないしは beforePost メソッドを呼ぶ。 ここでバリデーションやリダイレクトなどの実質的な処理を行うことになる。

サーブレットコンテキスト

behind に servletContext という名前のプロパティがあると、jspbp はサーブレットコンテキスト(javax.servlet.ServletContext) をコピーする。

セッション

セッションは? もちろん使える。だが、ちょっと待てほしい。セッションはグローバル変数のようなものだ。スコープを設けたほうがいい。 jspbp はスコープつきセッションとして、Persistent と Continuation という機能を提供する。

Persistent

behind クラスが org.kaoriha.jspbp.Persistent を implement している場合、jspbp は beforePost メソッドのあとで behind をセッションに保存する。保存以降のリクエストに対しては、jspbp は behind をいちいち構築せず、セッションから取り出してきて用いる。

この機能により、Redirect After Post パターン(別名 Post Redirect Get パターン、PRGパターン)が簡単に実現できる。 behind は beforePost メソッドの最後で response.sendRedirect(request.getRequestURI()); とするだけでいい。

Continuation

behind に continuation という名前の読み取り可能なプロパティがあり、beforePost メソッド内でリダイレクトした場合、 jspbp は continuation プロパティの値をセッションに保存する。そしてリダイレクト先の behind に continuation という名前の書き込み可能なプロパティがある場合、さきほどセッションに保存した値をセットする。

この機能により、フォームのチェーン( 『The Art of UNIX Programming』316ページ参照)が簡単に実現できる。

javax.servlet.http.HttpSession

それで、本物のセッションは? 答:beforeGet / beforePost メソッドの引数に HttpServletRequest と HttpServletResponse が渡されるので、そこから使える。cookie も同様だ。

JSPタグライブラリ

ささやかなおまけとして、jspbp の jar に、HTML の input / select / option / textarea 要素と一対一対応する JSP タグライブラリを同梱している。これは jspbp の behind と密接に結びついて動作する。 使い方は jspbp-helloworld のソースコードを参照すること。

jspbp-renderer も JSP タグライブラリだが、 こちらは jspbp と結びついていない。jspbp-renderer は、ビューのロジックとデザイン的な詳細の結合を疎に保つためのフレームワークである。 通常は behind で HTML を組み立ててしまう(jspbp-helloworld の JDOM テーブル参照)ほうが開発しやすいが、 jspbp-renderer を使うと、デザイン的な詳細を実装したクラスを JSP のタグで指定することができるので、 デザインのバリエーションが必要な場合に都合がいい。(特定顧客向けにカスタマイズするなど)

実行環境

  • J2SE 5.0 以降
  • Servlet 2.4 以降

ライセンス

プロジェクトライセンスを参照。

名前の由来

JSP Best Practice である。