こういうことをしたいのです。*1
A にヘッダー、B にメインコンテンツ、C にメニュー、D にフッターというよくあるレイアウトを実装する際に、A、C、D を毎回書きたくない。同じくらい強い気持ちで frameset は使いたくない。
Cubby が提供するレイアウト機能
これまでの経緯を踏まえ、ドキュメントをじっくり読んでみた。その結果として分かったことは「Cubby は独自のレイアウト機能を提供しない」ということである。
バージョン 0.9.1 までは
このままでは「できないことが分かりました」という非常に切ない結果で終わってしまうわけだが、それなりにダラダラと生き永らえてきた経験上、ここは「他の方法で代用可能だから提供していない」と読み替えることで活路を見出すことにする。
Cubby 以外が提供するレイアウト機能
ざっと考えた結果、以下のいずれかの方法を使えばレイアウトを実現できるのではないかと思うに至った。
- Mayaa のレイアウト共有 を使う
- Tiles を使う
- jsp-property-group を使う
1, 2 については 面倒くさい 程度の差はあれ導入コストが発生するため、3 の方法を使ってレイアウトの実現を試みることとする。
jsp-property-group はレイアウトのための機能ではないような気もするので、識者諸兄からすれば愚にも付かない試みかもしれないが、既存技術の応用と理解していただきたい。
jsp-property-group
Cubby の archetypeCatalog を使用してプロジェクトテンプレートを作成すると、web.xml には既に jsp-property-group の設定が記述されている。
<jsp-property-group> <url-pattern>*.jsp</url-pattern> <el-ignored>false</el-ignored> <page-encoding>UTF-8</page-encoding> <scripting-invalid>false</scripting-invalid> <include-prelude>/common/header.jsp</include-prelude> </jsp-property-group>
で、/common/header.jsp にはこのように記述されている。
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %> <%@ taglib prefix="t" uri="http://www.seasar.org/cubby/tags" %> <%@ taglib prefix="f" uri="http://www.seasar.org/cubby/functions" %>
おお!あのクソ面倒くさい taglib ディレクティブを毎回書かなくていい時代が来るなんて!(JSP 2.0 の仕様が最終決定したのは 2003/11/24)
include-coda
jsp-property-group タグの子要素に include-prelude タグを記述することで *.jsp にヘッダーを指定できるのと同様、include-coda タグを記述するとフッターを指定できる。
つまり、web.xml をこんなして
<jsp-property-group> <url-pattern>*.jsp</url-pattern> (中略) <include-prelude>/common/header.jsp</include-prelude> <include-coda>/common/footer.jsp</include-coda> </jsp-property-group>
header.jsp をこんなして
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="UTF-8" %> (中略) <html> <head> <title>cubby-test</title> </head> <body> <div id="header">Header</div> <div id="sidebar">Menu</div> <div id="main">
footer.jsp をこんなんすればいいんジャマイカ。
</div><!-- end of main --> <div id="footer">Footer</div> </body> </html>
の罠
ギャフン。
メインコンテンツに当たる JSP にバリデーションエラーやフラッシュメッセージを表示するための import タグが含まれていると・・・
<c:import url="/common/notice.jsp"/> <c:import url="/common/errors.jsp"/> <h2>Welcome Cubby-test</h2>
notice.jsp と errors.jsp それぞれにも header.jsp と footer.jsp が差し込まれて表示がブッ壊れた。
いや、そりゃあ *.jsp に include-prelude と include-coda を指定したのは確かにぼくだが、jsp-property の url-pattern はワイルドカード以外の正規表現は使えないし、ignore-url-pattern みたいな気の利いた子要素も無いし。
なんだか中途半端な仕様ですね。特定の名称は対象外にする、くらいできていい気がする。
結論
というわけで、現状はこんな感じに落ち着きました。
- レイアウトは jsp-property-group で行う
- 段組は css で行う
- include-prelude で指定する header.jsp には以下を記述する
- page ディレクティブ
- taglib ディレクティブ
- html 開始タグその他
- ヘッダー部分 html
- サイドバー部分 html
- メインコンテンツ部分開始タグ
- フラッシュメッセージ表示部分
- バリデーションエラー表示部分
- include-coda で指定する footer.jsp には以下を記述する
- メインコンテンツ部分終了タグ
- フッター部分 html
- html 終了タグその他
- メインコンテンツでは import タグを使わない
別にこれでもいいんじゃない?という感じもするけど、融通が利かない感も否めません。でもまあしばらくはこれでいいや、と思います。