JSTL でタグ属性に EL 式を書くとエラー

<c:forEach var=”org” items=”${organizations}”> 〜 </c:forEach>

の ${organization} など, タグの属性に EL 式を書くと

According to TLD or attribute directive in tag file, attribute items does not accept any expressions
(TLD やタグファイルの属性ディレクティヴによると、items 属性では式を使ってはいけないことになってますよ)

と怒られた(メッセージに従って EL 式を外すと通る)。何でだろうと悩んでいたら、
<%@taglib%> の uri によって参照しているバージョンが違うようで

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

としていたのを

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

に変更したら何事もなく動作した。ちなみに環境は
Apache Tomcat/5.5.9 + Jakarta Standard 1.1 Taglib/1.1.2 で、
JSTL については jstl.jar, standard.jar を WEB-INF/lib に入れたのと、
<%@taglib%> を宣言した以外は何もしていない。
どちらかでしか動作しないと思い込んでいたために気づくのが遅れ、これで
2 時間のロス。

jsp の動的 include について

いつも 静的 include (<%@ include path="foo.jsp"%>)だったが、初めて動的 include (<jsp:include /> を試してみた。
– 静的なものと違い, ローカル変数, メソッド定義, import 構文はそれぞれに独立
– page スコープの属性は互いに参照できない(pageContext の attribute など)
– request スコープ以降のものは参照可能。
なので影響範囲を最小にしつつ参照するには request スコープを使うとよい。
– jsp:param (ex. <jsp:param name=”foo” value=”123″ />)はリクエストパラメータ(request.getParameter(String))になる。
– jsp:include 呼び出しと通常のリクエストとを区別するには request スコープでやり取りするとよさそう。

ファイルアップロード "multipart/form-data" 処理のときに正しくパラメータを受け取るには

– form タグで ENCTYPE=”multipart/form-data” にすると ServletRequest.getParameter(Sting) 系ではパラメータを解釈できず全く値が渡って来なくなるため、Jakarta Commons FileUpload の org.apache.commons.fileupload.DiskFileUpload.parseRequest(…) 等を使うとよい。

// 適当に書いたコードなのでエラーあるかも。
DiskFileUpload o = new DiskFileUpload();
o.setSizeMax(-1);
o.setSizeThreshold(1024);
o.setRepositoryPath(“/tmp”);
o.setHeaderEncoding(“Windows-31J”);
List list = o.parseRequest(request); // FileItem のリスト
for(Iterator it = list.iterator(); it.hasNext();){
    FileItem param = (FileItem)it.next();
    if(!param.isFormField())
        continue();
    out.println(param.getFieldName() + “: ” + param.getString());
}

<http://www.jajakarta.org/commons/fileupload-1.0/ja/withoutPrimary/org/apache/commons/fileupload/DiskFileUpload.html#parseRequest(javax.servlet.http.HttpServletRequest,%20int,%20long,%20java.lang.String)>
– jajakarta.org: FileUpload API 1.0 (Ja)
<http://jakarta.apache.org/commons/fileupload/apidocs/org/apache/commons/fileupload/DiskFileUpload.html>
– Jakarta 公式: FileUpload API (current ver.)

ServletRequest インスタンスからリクエストされたパラメータのコレクションを抽出する

– サーブレットや JSP からクラスを抽出している際に、パラメータを使っているものを分離しようとして、 POJO に ServletRequest を渡すのはどうかなと思っていたところ、ちゃんとメソッドが提供されていた。
<http://java.sun.com/j2ee/sdk_1.3/ja/techdocs/api/javax/servlet/ServletRequest.html#getParameterMap()>
– ServletRequest#getParameterMap()

戻り値:
キーとしてパラメータ名、マップ値としてパラメータ値が格納された不変の java.util.Map。パラメータマップ内のキーは String 型。パラメータマップ内の値は String の配列型

たとえば次のコードが書かれたページ(test)にリクエストを送るとする:

// Arrays.toString(String[]) を利用しているため JDK5.0 以上でしか動かない。
out.println(“<table>”);
for(Iterator it = request.getParameterMap().entrySet().iterator(); it.hasNext();){
        Map.Entry entry = (Map.Entry) it.next();
        out.println(“<tr><td>”+entry.getKey()+”</td><td>”+Arrays.toString((String[])entry.getValue())+”</td></tr>”);
}
out.println(“</table>”);

結果は次の通り:

test?a=foo:
   a [foo]
test?a&b=boo&b=woo
   a []
   b [boo, woo]