Velocity

About

Community

Docs

Comparisons

Tools

Generation?

JSP touts as an advantage that it takes an existing .jsp page and compiles that into a Servlet for speed and efficiency reasons. What this means is that it first parses the .jsp page into the resulting mess below and then it uses javac or your favorite Java compiler (ie: Jikes) to compile that Servlet into a .class file which is then loaded by the Servlet Engine. Wow, just explaining all of that gave me a headache, how about you?

The point being that using JSP is now a multi step process. The authors of JSP have done a good job of hiding this process stuff behind the scenes in such a way that you do not even notice it. One simply edits the .jsp page in their favorite editor and then uses their browser to call the page via a URI which starts the process of transforming it into a .class file.

There are some fundamental issues that are being dealt with in the generated .jsp template. The first one is the class name. What happens is that the engine needs to produce a name that is unique in order to work around class loader issues that might crop up. Therefore, each and every time one modifies a .jsp page, a new file is created on disk in the temporary directory. Unfortunately, this directory ends up growing in size until someone decides to clean it up. The engine could probably do this for you, except then it might make the mistake of actually removing the wrong file.

The point being that this whole process of edit->transform->compile->load->run is really unnecessary and in particular, a bad design. On the other hand, Velocity will simply load templates, parse them a single time and then store an Abstract Syntax Tree (AST) representation of the template in memory which can then be re-used over and over again. The process is simply edit->parse->run. The benefit is that Velocity ends up being much faster and it also removes the requirement of having a javac compiler and temporary scratch directory hanging around. In Velocity, when the template changes, the existing cached template is simply replaced with a freshly parsed version.

Another advantage to Velocity's approach for templates is that the actual template data can be stored anywhere, including a database or remote URI. By using configurable template loaders, it is possible to create template loaders that can do anything that you want.

A .jsp page is really nothing more than a Servlet. By default, there is not a single shred of innovation there with regards to things like error handling or overall Model 2 architecture.

Even without Turbine, Velocity offers several ways to deal with errors. Where frameworks such as Struts and Turbine come handy is by providing ways of properly dealing with errors. However, due to the fact that Struts is based on top of JSP, it also inherits the same amount of problems associated with JSP. The next chapter will go into more details on that.

A major problem with the generated code is that it does not check to make sure that the output stream is still open before attempting to write to it. It also has the issue that if the stream is closed or an IOException is thrown while attempting to output to the stream, there is no way to catch it without using a specially defined error handler.

One final problem in the design shown below is that the JSP page only catches Exception's. What if the JSP page throws another exception like OutOfMemoryError? The problem here is that OOME is based on Throwable, not Exception. Therefore, it is much more difficult to catch this exception with just a JSP page.

This nice example provided by our friends at NASA, which sends multi-billion dollar equipment through the heavens, is a perfect example of why JSP needs better error handling.

Buffering is also another big issue as constantly writing to the output stream is not very efficient.

<%@ page buffer="12kb" %>
<%@ page autoFlush="true" %>

These are examples of telling JSP to buffer the output 12kb and to autoFlush the page. Struts+JSP has implemented the MVC model by providing the View portion through JSP templates. What part of the MVC model do you think that those tags belong? You guessed it, not the part where they are being used.

Velocity's approach to dealing with this issue is by allowing the developer to pass a stream into the rendering engine. If there is an exception thrown, during rendering, then the exception can be caught and dealt with. Buffering is also handled by passing properly buffered stream to the parser. Again, if there is an error, then another stream can be easily substituted for the output.

import javax.servlet.*;
import javax.servlet.http.*;
import javax.servlet.jsp.*;
import javax.servlet.jsp.tagext.*;
import java.beans.*;
import java.io.*;
import java.util.*;
import org.apache.jasper.runtime.*;
import org.apache.jasper.*;

public class _0002fhello_00031_0002ejsphello1_jsp_0 extends HttpJspBase {
    private static boolean _jspx_inited = false;

    public _0002fhello_00031_0002ejsphello1_jsp_0() { }

    public final void _jspx_init() throws JasperException { }

    public void _jspService(HttpServletRequest request, 
                            HttpServletResponse response)
                                throws 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();

            // HTML // begin [file="C:\\hello1.jsp";from=(0,0);to=(4,0)]
            out.write("<HTML>\r\n<HEAD><TITLE>Hello</TITLE></HEAD>\r\n<BODY>");
            out.write("\r\n<H1>\r\n");
            // end

            // begin [file="C:\\hello1.jsp";from=(4,2);to=(11,0)]
            if (request.getParameter("name") == null) {
               out.println("Hello World");
            }
            else {
              out.println("Hello, " + request.getParameter("name"));
            }
            // end

            // HTML // begin [file="C:\\hello1.jsp";from=(11,2);to=(15,0)]
            out.write("\r\n</H1>\r\n</BODY></HTML>\r\n\r\n");
            // end
        } catch (Exception ex) {
            if (out.getBufferSize() != 0)
                out.clearBuffer();
            pageContext.handlePageException(ex);
        } finally {
            out.flush();
            _jspxFactory.releasePageContext(pageContext);
        }
    }
}

You make the decision.

[ Saying Hello <- Previous | Next -> Error Handling ]


Copyright © 1999-2001, Apache Software Foundation