でjava.util.Mapの内容にアクセスする

Facelets内で使う場合だけではなく本物のJSTLを使う場合でも一緒かもしれないけど。
マニュアルではforEachのitemsはMapも取れることになっているけど、普通にループさせてもvaluesの方しか取り出せない(様に見える。) しかしデバッガで追ってみると、MappedValueExpressionが使われているので、キーにも値にもアクセスできるはず。
ソースを読んでいると、transientアトリビュートが真の場合にはMap.Entry自体が、それ以外の場合はMap.EntryのgetValueの値が使われるようになるようだ。

ForEachHandler.java:apply():

    boolean t = this.getTransient(ctx);
....
    if (t || srcVE == null) {
        ctx.setAttribute(vs, itrS);
    } else {
        ve = new IterationStatusExpression(itrS);
        vars.setVariable(vs, ve);
    }

ということで、キー-値のペアとして内容を取り出すにはアトリビュートにtransient="true"を指定すれば良い。(しかしドキュメントには何も書いてない。) 下のようにvarで指定した変数にMap.Entryがセットされてそれに.key、.valueでアクセスできるイメージ。

<c:forEach items="#{map}" var="entry" transient="true">
    <div class="entry-key">
        <h:outputText value="#{entry.key}" />
    </div>
    <div class="entry-value">
        <h:outputText value="#{entry.value}" />
    </div>
</c:forEach>

これでELがinstanceofに対応してくれたら基本タグだけでMap/Listの中身を再帰的に表示するコンポーネント(というかテンプレート)作れるのに。まあいいや。
ちなみに上のテンプレートでtransientを指定しないと、Bean: java.lang.String, property: valueとかいわれてcom.sun.facelets.tag.TagAttributeExceptionを投げられる。