Cocoon2のJSPReaderとJSPGeneratorを使う

 Cocoonでは、正しいXML文書またはXHTML文書を出力するJSPスクリプトを、 Cocoonパイプラインに埋め込むことができます。 JSPReaderはJSPスクリプトからXHTML文書を生成するときに、 JSPGeneratorはJSPスクリプトからXML文書を生成するときに使います。 JSPを書く段階では、両者の違いは全くないと思います。

 まず、sitemap.xmapの冒頭部に次のように JSPGeneratorとJSPReaderを追加します。

<map:generators default="file">
  <map:generator logger="sitemap.generator.jsp" name="jsp"
                 src="org.apache.cocoon.generation.JspGenerator"/>
</map:generators>
<map:readers default="resource">
  <map:reader logger="sitemap.reader.jsp" name="jsp" 
              src="org.apache.cocoon.reading.JSPReader"/>
</map:readers>

 ここで扱うサンプルは次のようなものです。まず、 下のようなタブ区切りのテキストファイル 「shiten.txt」があったものとして、これをJSPスクリプトで解析し、 XML文書にします。 その出力を受け取って、XSLスタイルシート shiten.xsl で整形して、出力します。

 shiten.txtです。

00100	東京	東京都港区北青山9-99-999	3	40
00120	さいたま	さいたま市桜田99-99	3	200
00200	横浜	横浜市中区根岸町9-99-999	3	200
00250	川崎	川崎市中原区木月住吉町99-99	3	100
00300	大阪	大阪市北区茶屋町9-99-999	5	250
00400	札幌	札幌市清田区北野9条99丁目999	1	200
00500	名古屋	名古屋市中区栄9-99-999	4	250
00600	仙台	仙台市青葉区中央9-99-999	2	100
00900	福岡	福岡市中央区天神9-99-999	8	200

 これを読んでXML形式で出力するJSPスクリプト、「shiten.jsp」です。

<?xml version="1.0" encoding="UTF-8"?>
<!-- ↑UTF-8にする必要あり -->
<%@ page language="java" contentType="text/html;charset=Shift_JIS" %>
<%@ page import="java.io.*, java.util.*" %>
<%@ page pageEncoding="Shift_JIS" %>
<data>
<%
  String fileName = "/usr/javadeploy/cocoon/cocoon-test/jsp/shiten.txt";

  try {
    BufferedReader reader = new BufferedReader(
      new InputStreamReader(new FileInputStream(fileName), "SJIS") );

    int rows = 0;
    while(true){
      String buf = reader.readLine();
      if(buf == null || buf.trim().equals("")) break;
      StringTokenizer tok = new StringTokenizer(buf, "\t");
%>
<shiten>
<shiten-code><%= tok.nextToken() %></shiten-code>
<shiten-name><%= tok.nextToken() + "です。" %></shiten-name>
<address><%= tok.nextToken() %></address>
</shiten>
<%
    }
    reader.close();
  } catch(IOException ex){
    out.println("エラー!ファイル読み取りエラーにより…");
  }
%>
</data>

注意点ですが、JSPGeneratorはエンコーディングがUTF-8でしか、 XML文書を生成できないようです。 そこで、1行目のxml version= encoding=のところのエンコーディングは 「UTF-8」を指定します。 但し、 このJSPスクリプト自体はシフトJISや日本語EUCでも構いません。 また、JSPの page pageEncoding擬似命令は必ず指定してください。 省略するとこれまた文字化けが発生してしまいます。

 そして、XSLスタイルシート「shiten.xsl」です。

<?xml version="1.0" encoding="Shift_JIS"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">

<xsl:output method="html" encoding="Shift_JIS" version="1.0"
   doctype-public="-//W3C/DTD XHTML 1.0 Strict/EN"
   doctype-system="DTD/xhtml1-strict.dtd" />

<xsl:template match="/data">
<html lang="ja">
<head><title>支店情報</title></head>
<body bgcolor="white">

<h2><font color="#700040">支店情報</font></h2>

<table border="1">
  <tr bgcolor="#ffcccc">
    <th>支店コード</th><th>支店名称</th><th>所在地</th>
  </tr>
  <xsl:for-each select="shiten">
    <tr>
    <td nowrap="1"><xsl:value-of select="shiten-code" /></td>
    <td nowrap="1"><xsl:value-of select="shiten-name" /></td>
    <td nowrap="1"><xsl:value-of select="address" /></td>
    </tr>
  </xsl:for-each>
</table>

</body></html>
</xsl:template>

</xsl:stylesheet>

 sitemap.xmapの書き方です。上記の例では、 shiten.jspは直接XHTMLを生成せず、XML文書を生成するので、 後者の書き方をすることになります。

<!-- JSPで直接XHTMLを生成する場合 -->
<map:match pattern="*.htm">
  <map:read type="jsp" src="{1}.jsp" mime-type="text/html" />
</map:match>

<!-- JSPでXMLを生成し、XSLTでXHTMLを生成する場合 -->
<map:match pattern="*.html">
  <map:generate type="jsp" src="{1}.jsp"/>
  <map:transform src="{1}.xsl"/>
  <map:serialize type="html"/>
</map:match>

 ここでもうひとつ注意ですが(多いなあ!)、 JSPの解析にはサーブレットコンテナ、例えばJakarta TomcatのJSPエンジン (Jasperと呼ばれています) を使います。 従って、要求するJSPスクリプトのパスは、 Cocoonから参照できるだけでなく、 同じパスでサーブレットコンテナからも参照できなければエラーになります。 Cocoonのサイトマップでmap:mountを使って隔離ディレクトリをマウントしている場合、 Cocoonからは見えてもサーブレットコンテナからは見えないパスというのができえますが、 それだとJSPはうまく動かないので注意が必要です。 私は結構はまりました。(-_-)
 なお、JSPエンジンとしてJasper以外のものを使う場合には、 $APP_HOME/WEB-INF/cocoon.xconf の次の部分を変更します。

<jsp-engine logger="core.jsp-engine">
  <parameter name="servlet-class" value="org.apache.jasper.servlet.JspServlet"/>
  <parameter name="servlet-name" value="*.jsp"/>
</jsp-engine>


その他のメモ

デバッグが大変
 JSP Readerなどを使ってJSPの開発を行った場合、JSPの構文エラーが起きた場合にも

org.apache.cocoon.ProcessingException: ServletException in JSPReader.generate()
というメッセージとスタックトレースしか表示されないため、 具体的にどのタグの構文がエラーなのかを知ることができません。 そこで、Cocoonとは別にサーブレット・コンテナに、 そのJSPを乗せて、初期表示が確認できる (少なくとも構文エラーが起きていないことが確認できる) 環境を作るのがお勧めです。 また、もっととりやすい解決策は、 この例外を発生させるCocoonのソースファイルJSPReader.javaの例外処理部を改造して、 ログにスタックトレースを表示させる(e.printStackTrace())文を追加する手もあります。 私はこの方法を使っています。

タグライブラリの使用
 JSP環境はサーブレットコンテナの機能に依存します。 それで当然、JSTLやJakarta Taglibsなどのタグライブラリも使えます。 使いたいときには、普通のJSPアプリケーションの場合と同じく、 $COCOON_HOME/WEB-INF にタグライブラリデスクリプタを置き、 $COCOON_HOME/WEB-INF/lib にそのクラスライブラリを置き、 $COCOON_HOME/WEB-INF/web.xml にタグライブラリの参照を書き加えます。

Baykit and Cocoon Top

(first uploaded 2003/02/02 last updated 2003/09/27, URANO398)

テレワークならECナビ Yahoo 楽天 LINEがデータ消費ゼロで月額500円〜!
無料ホームページ 無料のクレジットカード 海外格安航空券 海外旅行保険が無料! 海外ホテル