Velocity

About

Community

Docs

Tools

Comparisons

Site Translations

Error Handling

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!

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?

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

If you guessed that the error was a result of a missing ; 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.

Again, Velocity does not suffer from these same problems because there is no intermediate step and no layers of abstraction.

<%@ page errorPage="/error.jsp" %>

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

<% throw new Exception("oops"); %>

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.

<%
  if (true) {
    throw new Exception("oops");
  }
%>

The reason is that JSP will generate an additional out.println ("\r\n"); after the Exception. When javac attempts to compile the page, another hard to debug error will be reported:

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");
                ^

Taking a direct quote out of Jason's book (I couldn't say it better myself):

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.

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.

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 $foo and then attempts to call its substring() method on it would throw an IndexOutOfBoundsException:

#set ($foo = "bar")

#set ($bar = $foo.substring(0,10))

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.

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.

You make the decision.

[ Generation? <- Previous | Next -> JavaBeans ]



Copyright © 1999-2004, The Apache Software Foundation