<?xml version="1.0" encoding="Shift_JIS"?>
<document>

  <properties>
    <author email="jon@latchkey.com">Jon S. Stevens</author>
    <title>You make the decision - Error Handling</title>
    <translator>熊坂祐二</translator>
    <translator>高橋達男</translator>
    <translator>羽生田恒永</translator>
    <original>ymtd/ymtd-error-handling</original>
  </properties>

<body>

<section name="Error Handling" alias="エラー処理">

<primary>
<p>
This is a good one and a fundamental design issue with JSP. The question
is: How many different types of errors can one get when using JSP? For
example, because the JSP Servlet is auto generated from a .jsp text file
and then compiled with a compiler, what happens when there is a
generation/parsing error or a compile error? The unnecessary complexity
of JSP actually increases the number of ways to get errors!
</p>
</primary>
<p>
これは、JSP の典型的かつ根本的な設計の問題です。
JSP を使うとき、いったい何種類のエラーに遭遇するでしょうか?
例えば、JSP Servlet が、.jsp テキストファイルから自動生成されて、
コンパイラでコンパイルされ、生成/解析エラーやコンパイルエラーが
起こるとどうなるでしょうか? JSP が不必要に複雑なために、
エラーのパターンが実際に非常に多くなっているのです! 
</p>

<primary>
<p>
The ugliest aspect of all of this is the fact the errors are reported
via two different mechanisms. The parser can throw its own set of errors
and the javac compiler can throw a whole different set of errors and 
as a result of the layers of generation, errors from the compiler generally
do not make any sense whatsoever. For example, can you tell me what 
this error is from?
</p>
</primary>
<p>
この問題の中で最も美しくないのは、エラーが 2 つの異なる仕組みを通して報告される点です。
パーサは独自の種類のエラーを投げますし、
javac コンパイラもまた別の種類のエラーを投げます。
生成までにいくつもの手順を踏むことで、コンパイルエラーはまったく意味不明になっています。
例えば、このエラーがどこで起こったか、説明できますか? 
</p>

<source><![CDATA[
org.apache.jasper.JasperException: Unable to compile class: Invalid type
expression.
                out.println("JSP is great!")
                           ^
: Invalid declaration.
                out.write("\r\n\r\n\r\n");
                         ^
2 errors
]]></source>

<primary>
<p>
If you guessed that the error was a result of a missing <code>;</code>
after the first out.println(), you were correct! Now, put yourself in
the shoes of someone who has never written or seen a line of Java code.
Do you think that person could have figured out the error quickly and
easily? Compound that with the fact that if the error had been on a less
deterministic part of the file, it is now much harder to find the source
of the error because there is a level of abstraction from the original
.jsp file and because there is an intermediate .java file that gets
generated.
</p>
</primary>
<p>
エラーの原因が最初の out.println() の後に<code>;</code>
が抜けていたせいだとわかったあなたは正解です!
さて、Java のコードを書いたことも見たこともない人の立場に立ってみましょう。
そういう人がこのエラーを迅速かつ容易に理解できると思いますか? 
それに加えて、このエラーの発生した場所が、その原因となった場所とは違う場所だった場合、
元の .jsp ファイルから抽象化されたレイヤがあり、
さらに生成された中間的な .java ファイルがあるため、
エラーの原因となった場所を見つけるのは困難です。
</p>

<primary>
<p>
Again, Velocity does not suffer from these same problems because there
is no intermediate step and no layers of abstraction.
</p>
</primary>
<p>
繰り返しますが、Velocity には、中間ステップも抽象化レイヤもないので、
これと同じ問題で苦しむことはありません、
</p>

<source><![CDATA[
<%@ page errorPage="/error.jsp" %>
]]></source>

<primary>
<p>
JSP also allows one to define an error page that is used if an Throwable
exception is thrown during the processing of a page. Doesn't this again
break the MVC model? In other words, shouldn't the application framework
be responsible for dealing with error messages
</p>
</primary>
<p>
また、JSP では Throwable な例外がページの処理中に投げられたときに
使用するエラーページを定義できます。
これもまた、MVC モデルを破壊することにならないでしょうか? 
言い換えれば、アプリケーションフレームワークが
エラーメッセージの扱いに責任を持てないのです。
</p>

<source><![CDATA[
<% throw new Exception("oops"); %>
]]></source>

<primary>
<p>
In order to throw an Exception somewhere in a JSP page, one needs to
first embed it within a statement. Note: that in this specific case, if
optimizations are turned on in the compiler, chances are that the entire
exception would be compiled out. Therefore, a more concrete object must
be used instead of the "true". This can actually prove difficult if
using a strict MVC model because instantiation of objects breaks the
View.
</p>
</primary>
<p>
JSP ページのどこかで Exception を投げるためには、
ステートメントの中に最初にそれを埋め込む必要があります。
この特殊なケースでは、コンパイラで最適化が有効になっている場合、
例外が全てコンパイルされない可能性があることに注意してください。
したがって、[下記の例の]「true」の代わりに、
具体的なオブジェクトを使わなければなりません。
厳密な MVC モデルを使うなら、この方法は現実的には難しいかもしれません。
なぜなら、オブジェクトの生成処理が View を破壊するからです。

</p>

<source><![CDATA[
<%
  if (true) {
    throw new Exception("oops");
  }
%>]]></source>

<primary>
<p>
The reason is that JSP will generate an additional <code>out.println
("\r\n");</code> after the Exception. When javac attempts to compile the
page, another hard to debug error will be reported:
</p>
</primary>
<p>
その理由は、JSP が Exception の後に追加で <code>out.println("\r\n");</code>
を生成するからです。javac がページをコンパイルしようとするときに、
デバッグしづらい別のエラーが起こります。
</p>

<source><![CDATA[
org.apache.jasper.JasperException: Unable to compile class for
  JSPC:\engines\jakarta-tomcat\work\localhost_8080%2Fjsp\
  _0002ferrorMaker_0002ejsperrorMaker_jsp_3.java:75:
Statement not reached.
                out.write("\r\n");
                ^]]></source>

<primary>
<p>
Taking a direct quote out of Jason's book (I couldn't say it better myself):
</p>
</primary>
<p>
(自分ではうまく説明できないので) 直接 Jason の書籍から引用すると
</p>

<primary>
<source><![CDATA[
In fact, there are many such "gotchas" when using scriptlets with JSP. 
If you accidentally write a scriptlet instead of an expression (by
forgetting the equal sign), declare a static variable inside a scriptlet
(where statics aren't allowed), forget a semi-colon (they're not needed
in expressions but are needed in scriptlets), or write anything but
perfect Java code, you're likely to get a confusing error message
because the compiler is acting on the generated Java code, not on the
JSP file.  To demonstrate the problem, picture if <%= name %> were
replaced by <% name %> in errorTaker.jsp.  Tomcat generates this error:

org.apache.jasper.JasperException: Unable to compile class for
  JSPC:\engines\jakarta-tomcat\work\localhost_8080%2Fjsp\
  _0002ferrorTaker_0002ejsperrorTaker_jsp_6.java:91:
Class name not found.
                 name 
                 ^

Debugging an error like this often requires a programmer to look at the
generated code to reconstruct what caused the error.]]></source>
</primary>
<source><![CDATA[
実際、JSP スクリプトを使う時には、こんな風に「なるほど…そういうことか!」
と思う機会が多いのです。たまたま式を書き忘れて ("=" 記号を忘れて)
スクリプトレットを書いてしまったり、(staticは許されない)
スクリプトレット内で static 変数の定義をしたり、
(式には不要だが、スクリプトレットには必要な)セミコロンを忘れたり、
たまたま全然ダメな Java コードを書いてしまったりしてしまうと、
意味不明なエラーメッセージが出る可能性があります。なぜなら、
コンパイル処理は JSP ファイルではなく生成された Java コードに対して
行われるからです。この問題を具体的に示すために、
errorTaker.jsp ファイルで <%= name %> とすべきところを
<% name %> としてみましょう。Tomcat は以下のエラーを生成します。

org.apache.jasper.JasperException: Unable to compile class for
  JSPC:\engines\jakarta-tomcat\work\localhost_8080%2Fjsp\
  _0002ferrorTaker_0002ejsperrorTaker_jsp_6.java:91:
Class name not found.
                 name 
                 ^

このようなエラーをデバッグする際、エラーの発生を再現するために、
プログラマが生成されたコードを
見なければならないことも少なくありません。]]></source>

<primary>
<p>
Velocity does not have of these same problems because it does not allow
the author to place any Java code within a template. The only things allowed
in the template are Velocity Template Language (VTL) and method calls.
</p>
</primary>
<p>
Velocity では、テンプレート内部にどんな Java コードも埋め込むことを
許可していないため、同じ問題は発生しようがありません。
テンプレートで唯一許されるのは Velocity テンプレート言語（VTL）と
メソッド呼び出しだけです。
</p>

<primary>
<p>
Everything else is considered 'text' for literal output by the parser.
The only place where one could run into trouble within Velocity is if
there is a call to a method which throws an exception during runtime.
For example, this VTL defines a String <code>$foo</code> and then
attempts to call its <code>substring()</code> method on it would throw
an <code>IndexOutOfBoundsException</code>:
</p>
</primary>
<p>
それ以外は全てパーサが「テキスト」と見なしてそのまま出力されます。
Velocity でトラブルが起こるのは、実行中に例外を投げるメソッドを呼び出す時だけです。
例えば、以下の VTL では <code>$foo</code> という String が定義されており、
その <code>substring()</code> メソッドを呼びだそうとすると、
<code>IndexOutOfBoundsException</code> が投げられるかもしれません。
</p>

<source><![CDATA[
#set ($foo = "bar")

#set ($bar = $foo.substring(0,10))
]]></source>

<primary>
<p>
When the exception is thrown, the parser will stop processing and throw
that exception up the stack tree where it can be caught in the method
that caused the parser to execute. At that point, the exception can be
handled gracefully. Yes, this is something that is probably not easily
debugged by a Designer without Java knowledge, it is easily debugged by
a Template Engineer who has at least limited Java knowledge.
</p>
</primary>
<p>
例外が投げられると、パーサは処理を停止し、
パーサが実行したメソッドで例外が捕捉された時点のスタックツリーに
その例外を吐き出します。その時点で、例外は無理なく扱うことができます。
そうです、この例外は、Java の知識のないデザイナにはデバッグが難しいかも知れませんが、
少なくともある程度の Java の知識があるテンプレートエンジニアならデバッグは簡単なのです。
</p>

<primary>
<p>
This is one of the benefits of using Turbine combined with Velocity
because of Turbine's design it easy to deal with Exceptions in a
consistent manner. It is also possible to get this same functionality
with by using Velocity's included VelocityServlet. The Exception will
contain the line number and column number in the .vm file of where the
error happened. Because there is no abstraction like with JSP, the line
number and column matches up to the error. Also, the only tool that will
throw the exception is the parser and that exception will contain the
location and error information pertinent to your actual template, not an
intermediary file. No need to try to debug the cryptic javac messages
which are a result of generated .java code. Note: one commercial
application server offers better handling of matching the line number in
the JSP file to the error.
</p>
</primary>
<p>
これは Velocity との組み合わせで Turbine を使う利点の1つです。
というのは Turbine の設計は、一貫性のある方法で例外を取り扱うからです。
また、Velocity に含まれている VelocityServlet を使ってもこれと同じ機能が実現できます。
その例外には、エラーが発生した.vmファイル内の行番号とカラム番号が含まれています。
JSP のように抽象化を行わないので、エラーの行番号とカラム番号が一致します。
また、例外を投げるのはパーサだけであり、中間の .java ファイルではなく、
実際のテンプレートに関連した場所情報やエラー情報がこの例外には含まれています。
自動的に生成された .java コードに対する、不可解な javac メッセージをデバッグする必要はありません。
注意: 商用のアプリケーションサーバの中には、
エラー時に JSP ファイルの行番号をうまく扱うものがあります。
</p>

<primary>
<p>
You make the decision.
</p>
</primary>
<p>
[どちらを選ぶかは] あなたが判断してください。
</p>

<primary>
<p>
<strong>[ <a href="ymtd-generation.html">Generation?</a> &lt;- Previous | 
    Next -&gt; <a href="./ymtd-javabeans.html">JavaBeans</a> ]
</strong></p>
</primary>
<p>
<strong>[ <a href="ymtd-generation.html">生成?</a> &lt;- 前 | 
    次 -&gt; <a href="./ymtd-javabeans.html">JavaBeans</a> ]
</strong></p>

</section>

</body>
</document>

