JSP2.0とカスタムタグ

JSP2.0になってから、JSPファイルを記述するように手軽にカスタムタグを作れるようになりました。また、それにあわせて、TagやBodyTagの系列とは別に SimpleTag なるものも増えています。

SimpleTagを使用した場合、従来はdoStartTagメソッドやdoEndTagメソッドなどで処理を記述していたのに対して、すべてdoTagメソッドに記述することができます。
ボディ部の繰り返し等についても、doTag内でボディ部を表すJSPフラグメントを複数回評価するだけで済みます。

また、それとは別に、タグファイルを使用すれば、タグクラスを作ることなくカスタムタグを作ることができます。タグファイルの記述はJSPのそれとほぼ同じであり、カスタムタグを作る上で固有のディレクティブや標準アクションがあるぐらいです。
JSTLで用意されている繰り返しや条件分岐とEL等を組み合わせることにより、複雑なものでなければ、ほとんどのカスタムタグはタグファイルによって作ることができると思います。

しかし、そんなタグファイルにも弱点が・・・
今日はその弱点に嵌ってしまい、数時間を無駄に消費してしまいました。
タグファイルが評価される場合、JSPと同様にコンテナによってJavaのクラスにされます。
親クラスとして SimpleTagSupport が指定されたカスタムタグクラスが作成されるのですが、なぜか親タグは設定されず、またページコンテキストも土台となったJSPのページコンテキストとは別のものが設定されます。*1
どうやら、タグファイルを使用した場合、生成されるバイナリはカスタムタグの形態をとるものの、扱いとしてはJSPに近いようです。そのため、別のページとしてみなされ、親タグの情報や、ページコンテキストは引き継がれないようです。

そのため、親子関係のある複数のタグで一つの処理を行なうような場合、それらのタグ間に、タグファイルを使用したタグが挟まると、正しく動作しなくなってしまいます。

  以下のようなカスタムタグがあった場合に
  <x:parent>
    <x:child value="..."/;>
  </x:parent>

  childタグをタグファイルでくるんだ場合(tags:child タグ)
  <% tag %>
  <% attribute ... >
  <x:child value="${xxxx}"/>

  こういう使い方をすると
  <x:parent>
    <tags:child value="..."/;>
  </x:parent>

  x:childタグの親を辿っても x:parent にたどり着けません。
  また、タグファイル内と外とで異なるページコンテキストであるため、ページスコープの属性を使用した値のやり取りもできません。

getParent をしても親は取れませんし、ページコンテキストに属性を設定しても、親子で違うコンテキストに属するため、値のやり取りは出来ません。
カスタムタグの動作としては気持ち悪いのですが、リクエスト属性に設定する等して値のやり取りを行なう必要があります。

*1:TOMCAT5.5の場合です。他のコンテナではどなのかは未確認です。JSPの仕様をみても、とくに明記されていないように思えます。