Sevlet2.4/JSP2.0 Upgrade Hell(2年のブランク)

私はJavaから2年程離れていた訳だが、その間に

Servlet2.3 -> Sevlet2.4
JSP1.1 -> JSP2.0

とWebアプリケーションのコアコンポーネントがバージョンアップされている。まあ、変更は細かい部分だと聞いているしEJB程ドラスティックな変更は無いから当時のアプリケーション等は新しいコンポーネント上でもさくっと動くだろうと軽く考えて作業をしていたのだが、甘かった。

WebアプリケーションのDD(Deployment Descriptor)である、web.xmlで使用するスキームがDTDからXMLSchemaに変更された。

2.3 DOCDYPTE宣言

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

2.4 XMLSchema宣言

<web-app xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

一応2.3のDTDに対して下位互換はあるのだが、要素の親がルートではなく要素になる等、細かい点でいろいろと変わっているので、今後の事を考えると2.4にせざるを得なかった。また、後述するがこのDDのバージョンとJSTLのバージョン、コンテナのバージョンにより問題が発生することが判明した。

taglibの扱い(TLDの場所解決方法)が変わったのは知っていたが、なによりはまったのがJSTL(Java Standard Tag Liblary)の参照URIのバリエーションが知らない間に増えたことに対してだ。

外部で定義されたカスタムタグライブラリィを参照するには、そのタグを参照する際の(仮の)URIが必要であり、初期のJSTLを使用する場合は以下のようにtaglibディレクティブを書く必要があった

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

この参照先が違うとJSP上でのタグのバリデーションポリシも変わるようで、私の場合Tomcat 5.5.20上でJSTL1.0を使用したのだが、同様の記述を行うとHTMLタグ下でJSTLを使った際に式を書けない、という意味のエラーが発生するようになってしまった。

org.apache.jasper.JasperException: /index.jsp(line,column) According to TLD or attribute directive in tag file, attribute value does not accept any expressions
org.apache.jasper.compiler.DefaultErrorHandler.jspError(DefaultErrorHandler.java:39)
org.apache.jasper.compiler.ErrorDispatcher.dispatch(ErrorDispatcher.java:409)
org.apache.jasper.compiler.ErrorDispatcher.jspError(ErrorDispatcher.java:150)
org.apache.jasper.compiler.Validator$ValidateVisitor.checkXmlAttributes(Validator.java:941)
org.apache.jasper.compiler.Validator$ValidateVisitor.visit(Validator.java:696)
:
:(line,column)はJSPコンパイル時のエラー発生箇所

最初は何故エラーが発生するのかが全く解らなかったのだが、sunのdeveloper forumでこんなwork aroundを見つけた。

jstl foreach loop attribute items does not accept any expressions'

症状としては私と全く同じなので、同様にuriを以下のように書き換えるとEL式が元のように使えるようになった。
旧(STL1.0?)

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core" %>

新(STL1.1?)

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>

どころが、どうも新たな記述方法が良いとは限らないようなのだ。というのもいろいろと調べてみると、サーブレットコンテナのバージョンと、JSTLライブラリィのバージョン、そしてサーブレット/JSPのバージョンの組み合わせによって問題を引き起こすようなのだ。

HowTo: Upgrade your app to JSP 2.0 - Raible Designs

URI HELL: Juggling JSTL Taglib URI settings in JSP pages - Segmentation Fault: Core dumped..;-)
(私のケースは一番最後に近い。Tomcat 5.5.20, JSTL1.0.5, servlet/jsp 2.3/1.1, web.xml 2.4 Schema)

org.apacheでもこのような状況なのだから、他のOSSを組合わせた場合に問題が発生することは容易に想像がつくだろう。(必ずといって良いほど自分と同じ境遇のデベロッパが見つかるものだ)

これこそがJavaを、OSSを組合わせて使う上で一番懸念すべきことである。


追記:

JSTLを1.1に上げれば解決かと思ったのだが、駄目だった。JSTL1.1は標準では以下のURIを指定する必要があるので、JSPの修正が必要なのは変わらない。

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

上で書いた

<%@ taglib prefix="c" uri="http://java.sun.com/jstl/core_rt" %>

でも動くのだが、正式ではないとのこと。混乱するなぁ。