<?xml version="1.0" encoding="Shift_JIS"?>
<document>

  <properties>
    <author email="jon@latchkey.com">Jon S. Stevens</author>
    <title>You make the decision - Generation?</title>
    <translator>熊坂祐二</translator>
    <translator>高橋達男</translator>
    <original>ymtd/ymtd-generation</original>
  </properties>

<body>

<section name="生成?">

<p>
JSPでの利点として、既存の .jsp ページを速度と効率上の理由からコンパイルして
Servletにできることが喧伝されています。
それがどういうことかと言えば、まず .jspページを解析し、
このページの最後に出てくるようなごちゃごちゃしたコードにした上で、
javacや、あなたの好きな Java コンパイラ (例えば Jikes) で、この Servletが
.class ファイルにコンパイルされ、それから Servlet エンジンにロードされます。
ふぅ・・・これを説明するだけで頭痛がしてきましたが、いかがですか?
</p>

<p>
要するに、今のところ、JSP を使うには多段階のプロセスが必要だということです。
JSP の作者は、ユーザがプロセスがあることさえ気がつかないぐらい、
こうしたプロセスのあれこれを裏に隠すのに成功しています。
ユーザは好きなエディタで .jsp ページを編集し、ブラウザを使って、
ページを .class ファイルに変換するプロセスを開始する URI 経由で、
ページを呼び出すだけです。
</p>

<p>
生成された .jsp テンプレートにはいくつかの根本的な問題があります。
まずは、そのクラス名です。つまり、クラスローダーの問題に対処するために、
エンジンはユニークな名前を生成する必要があるということです。
したがって、誰かが .jsp ページを修正するたびに、
新しいファイルがディスクのテンポラリディレクトリに作成されます。
残念なことに、誰かがそれを掃除しない限り、
このディレクトリのサイズは増えつづけることになります。
ひょっとしたらエンジンが代わりに削除してくれるかもしれませんが、そうすると、
間違って、削除してはならないファイルを削除してしまうかもしれません。
</p>

<p>
要するに、編集-&gt;変換-&gt;コンパイル-&gt;ロード-&gt;実行という全体のプロセスは、
実際不必要ですし、何より設計として良くないということです。
それに対して、Velocity は単にテンプレートをロードし、一度だけ解析し、
何度でも再利用できるように、テンプレートを抽象構文木（AST）表現でメモリに格納します。
プロセスは、単に編集-&gt;解析-&gt;実行と、単純です。
利点としては、Velocity テンプレートを使うと非常に処理が速くなり、
javacコンパイラとテンポラリディレクトリの間を行ったり来たりする必要がなくなることです。
Velocityでは、テンプレートを変更する際も、既存の蓄積されたテンプレートが、
新たに解析されたバージョンと置き換わるだけです。
</p>

<p>
テンプレートを使う Velocity のアプローチのもう一つの利点は
実際のテンプレートデータをどこにでも格納できることです。
格納場所としてはデータベースやリモートURIも含まれます。
設定可能なテンプレートローダーを使用することにより、
何でもできるテンプレートローダーを作成することが可能です。
</p>

<p>
Turbine がなくても、Velocity でエラー処理を行う方法がいくつかあります。
Struts や Turbine といったフレームワークの便利なところは、
エラー処理を適切に行えることです。
しかし、Struts は JSP に基礎を置いているという事実のために、
JSP に関する問題を JSP と同じだけ引き継いでいます。
次の章では、これに関してさらに詳細に説明します。
</p>

<p>
後述される設計の問題の中でも決定的なものとして、
JSP ページは <code>Exception</code> しか捕えられないことです。
もし、JSP ページが <code>OutOfMemoryError</code>
といった他の例外を投げたらどうなるでしょうか?
ここでの問題は、OutOfMemoryError が (<code>Exception</code> ではなく)
<code>Throwable</code> ベースにしているということです。
したがって、JSP ページだけでこの例外を捕えるのは、ずっと難しいです。
将来のバージョンの JSP 仕様・実装では、これに関しては改善される予定です。
</p>

<p>
この<a href="./images/jsp-nasa-crash.gif" target="newWindow">すてきな例</a>は、
NASA (数10億ドルの機器を天国に飛ばしています) の友人が提供してくれたもので、
JSP でのエラー処理の改善がなぜ必要か、ということに関する完璧な例です。
</p>

<p>
バッファリングはもう一つの大きな問題です。なぜなら、
絶えず出力ストリームに書くのはあまり効率的でないからです。
</p>

<source><![CDATA[
<%@ page buffer="12kb" %>
<%@ page autoFlush="true" %>
]]></source>

<p>
この例では、出力を 12kb だけバッファリングし、ページを autoFlush するように
JSP に命令します。Struts と JSP の組み合わせでは、JSP テンプレートで
View の部分を提供することによって、MVC (Model-View-Controller) モデルを実装しています。
上記のタグは MVC モデルのどこに属していると思いますか?
ご想像の通り、ここ [View] はこれらのタグを使うべきところではありません。
</p>

<p>
この問題に対する Velocity でのアプローチは、
開発者がテンプレート処理エンジンにストリームを渡すというものです。
テンプレート処理の途中で例外が投げられたら、例外を捕えて処理できます。また、
バッファリングについては、パーサに適切にバッファされたストリームを渡すことで
対応できます。この場合も、エラーが発生したら、
その出力の代わりに別のストリームを使うこともできます。
</p>

<p>
これは、Tomcat 3.3 m2 で生成された中間コードの例です。
</p>

<source><![CDATA[
package jsp;

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;

public class helloworld_1 extends org.apache.jasper.runtime.HttpJspBase {

    static {
    }
    public helloworld_1( ) {
    }

    private static boolean _jspx_inited = false;

    public final void _jspx_init() throws org.apache.jasper.JasperException {
    }

    public void _jspService(HttpServletRequest request, HttpServletResponse  response)
        throws java.io.IOException, ServletException {

        JspFactory _jspxFactory = null;
        PageContext pageContext = null;
        HttpSession session = null;
        ServletContext application = null;
        ServletConfig config = null;
        JspWriter out = null;
        Object page = this;
        String  _value = null;
        try {

            if (_jspx_inited == false) {
                _jspx_init();
                _jspx_inited = true;
            }
            _jspxFactory = JspFactory.getDefaultFactory();
            response.setContentType("text/html;charset=8859_1");
            pageContext = _jspxFactory.getPageContext(this, request, response,
			"", true, 8192, true);

            application = pageContext.getServletContext();
            config = pageContext.getServletConfig();
            session = pageContext.getSession();
            out = pageContext.getOut();

            out.write("<html>\r\n<head><title>Hello</title></head>\r\n<body>\r\n<h1>\r\n");
            if (request.getParameter("name") == null) 
              out.write("\r\n          Hello World\r\n");
            else 
              out.write("\r\n          Hello, ");
            request.getParameter("name"); 
              out.write("\r\n</h1>\r\n</body></html>\r\n");

        } catch (Exception ex) {
            if (out != null && out.getBufferSize() != 0)
                out.clearBuffer();
            if (pageContext != null) pageContext.handlePageException(ex);
        } finally {
            if (out instanceof org.apache.jasper.runtime.JspWriterImpl) { 
                ((org.apache.jasper.runtime.JspWriterImpl)out).flushBuffer();
            }
            if (_jspxFactory != null) _jspxFactory.releasePageContext(pageContext);
        }
    }
}
]]></source>

<p>
[どちらを選ぶかは] あなたが判断してください。
</p>
<p>
<strong>[ <a href="ymtd-saying-hello.html">Saying Hello</a> &lt;- 前 | 
    次 -&gt; <a href="./ymtd-error-handling.html">エラーの扱い</a> ]
</strong></p>

</section>

</body>
</document>

