Servlets.com

Home

What's New?

com.oreilly.servlet

Servlet Polls

Mailing Lists

Servlet Engines

Servlet ISPs

Servlet Tools

Documentation

Online Articles

The Soapbox

"Java Servlet
Programming,
Second Edition"

"Java Enterprise
Best Practices"

Speaking & Slides

About Jason

XQuery Affiliate

The Problems with JSP
January 25, 2000

by Jason Hunter

Note: In the time since this essay was written, JSP has gone through two updates and can now be considered better (although yet more complicated) than it was when this article was written. However, JSPs competitors have not been idle and in addition to WebMacro we now have Apache Velocity and my personal favorite, Tea, from the Walt Disney Internet Group (WDIG). For an in-depth discussion of JSP and its competitors, see the 2nd Edition of my book Java Servlet Programming.

By now almost everyone using servlets has heard about JavaServer Pages (JSP), a Sun-invented technology built on top of servlets. Sun has done a marvelous job promoting JSP as a way to get HTML out of servlet code, speeding web application development and improving web page maintenance. In fact, the official "Application Programming Model" document published by Sun has gone so far as to say, "JSP technology should be viewed as the norm while the use of servlets will most likely be the exception." (Section 1.9, December 15, 1999, Draft Release) This paper evaluates whether that claim is valid -- by comparing JSP to another technology built on servlets: template engines.

The Problem with Straight-up Servlets

In the beginning, servlets were invented, and the world saw that they were good. Dynamic web pages based on servlets executed quickly, could be moved between servers easily, and integrated well with back-end data sources. Servlets became widely accepted as a premiere platform for server-side web development.

However, the commonly-used simple approach to generating HTML content, having the programer write an out.println() call per HTML line, became a serious problem for real servlet use. HTML content had to be created within code, an onerous and time consuming task for long HTML pages. In addition, content creators had to ask developers to make all content changes. People searched for a better way.

Along Comes JSP

Around this time JSP 0.90 came along. With this new technology you could put snippets of Java code inside your HTML, and the server would automatically create a servlet from the page. This helped quite a lot. There was no attempt to hide the Servlet API; JSP was considered a "cheap" way for a Java programmer to write a servlet. All the HTML code could be included directly without out.println() calls and page creators could make changes to the HTML without serious risk of breaking the Java code.

But having artists and developers working on the same file wasn't ideal, and having Java inside HTML proved almost as awkward as having HTML inside Java. It could easily create a hard to read mess.

So people matured in their use of JSP and started to rely more on JavaBeans. Beans were written to contain business logic code needed by the JSP page. Much of the code inside the JSP page could be moved out of the page into the bean with only minimal hooks left behind where the page would access the bean.

More recently, people have started to note that JSP pages used this way are really a "view". They're a component used to display the results of a client request. So people thought, Why submit a request directly to a "view"? What if the targetted "view" isn't the proper view for that request? After all, many requests have several possible resulting views. For example, the same request might generate a success page, a database exception error report, or a required parameter missing error report. The same request might also generate a page in English or a page in Spanish, depending on the client's locale. Why must a client directly submit its request to a view? Shouldn't the client make a request to some general server component and let the server determine the JSP view to return?

This belief caused many people to adopt what has been called the "Model 2" design, named after an architecture laid out in the JSP 0.92 specification and based on the model-view-controller pattern. With this design, requests are submitted to a servlet "controller" that performs business logic and generates an appropriate data "model" to be displayed. This data is then passed internally to a JSP page "view" for rendering, where it appears to the JSP page like a normal embedded JavaBean. The appropriate JSP page can be selected to do the display, depending on the logic inside the controlling servlet. The JSP page becomes a nice template view. This was another improvement -- and where many serious developers stand today.

Enter Template Engines

But why suffer the complexity of JSP just to do templating? Might it not be better to use a dedicated template engine? By using a template engine intended for this exact use instead of the general-purpose JSP, the underlying design can be cleaner, the syntax clearer, the error messages more meaningful, and the tool more customizable. Several companies have built such engines, the most popular probably being WebMacro (http://webmacro.org, from Semiotek) whose engine is free.

Using a dedicated template engine instead of JSP offers several technical advantages that developers should be aware of:

Problem #1: Java Code Too Tempting

JSP makes it tempting to put Java code in the web page, even though that's considered bad design. Just as Java improves on C++ by removing the ability to use global variables and multiple inheritance, so do template engines improve on JSP by removing the ability to put raw code in the page. Template engines enforce good design.

Problem #2: Java Code Required

Doing mundane things in JSP can actually demand putting Java code in the page. For example, assume the page needs to determine the context root of the current web application to create a link to the web app home page:

In JSP this is best done using Java code:

<a href="<%= request.getContextPath() %>/index.html">Home page</a>

You can try to avoid Java code using the <jsp:getProperty> tag but that leaves you with the following hard-to-read string:

<a href="<jsp:getProperty name="request"
property="contextPath"/>/index.html">HomePage</a>

Using a template engine there's no Java code and no ugly syntax. Here's the same command written in WebMacro:

<a href="$Request.ContextPath;/index.html">Home page</a>

In WebMacro, ContextPath is seen as a property of the $Request variable, accessed using a Perl-like syntax. Other template engines use other syntax styles.

An another example where JSP requires Java code in the page, assume an advanced "view" needs to set a cookie to record the user's default color scheme -- a task that presumably should be done by the view and not the servlet controller. In JSP it requires Java code:

<% Cookie c = new Cookie("colorscheme", "blue"); response.addCookie(c); %>

In WebMacro there's no Java code:

#set $Cookie.colorscheme = "blue"

As a last example, assume it's time to retrieve the color scheme cookie. For the benefit of JSP, we can presume also there's a utility class available to help since doing this raw with getCookies() is ridiculously difficult. In JSP:

<% String colorscheme = ServletUtils.getCookie(request, "colorscheme"); %>

In WebMacro there's no need for a utility class and it's always:

$Cookie.colorscheme.Value

For graphics artists writing JSP pages, which syntax would be simpler to learn?

JSP 1.1 introduced custom tags (allowing arbitrary HTML-like tags to appear in JSP pages executing Java code on the backend) which may help with tasks like this, assuming there becomes a widely known, fully featured, freely available, standardized tag library. So far that has yet to occur.

Problem #3: Simple Tasks are Hard

Doing even a simple task such as header and footer includes is overly difficult with JSP. Assume there's a "header" template and a "footer" template to be included on all pages, and each template includes in its content the current page title.

In JSP the best way to do this is as follows:

<% String title = "The Page Title"; %>
<%@ include file="/header.jsp" %>
  Your content here
<%@ include file="/footer.jsp" %>
Page creators must not forget the semi-colon in the first line and must make sure to declare title as a Java String. Plus, the /header.jsp and /footer.jsp must be made publicly accessible somewhere under the document root even though they aren't full pages themselves.

In WebMacro including headers and footers is done easily:

#set $title = "The Page Title"
#parse "header.wm"
  Your content here
#parse "footer.wm"
There are no semi-colons or String types for designers to remember, and the .wm files are found in a customizable search path, not under the document root.

Problem #4: Lousy Looping

Looping is overly difficult in JSP. Here's the JSP code to iterate over a vector of ISP objects printing the name of each.
<%
  Enumeration e = list.elements();
  while (e.hasMoreElements()) {
    out.print("The next name is ");
    out.println(((ISP)e.nextElement()).getName());
    out.print("<br>");
  }
%>
Someday there will be custom tags for doing these loops. And custom tags for "if" checks too. And JSP pages may look like a grotesque Java reimplemented with tags. But meanwhile, the webmacro loop is already quite nice:
#foreach $isp in $isps {
  The next name is $isp.Name <br>
}
The #foreach directive could be replaced by a custom #foreach-backwards directive fairly easily as well if such a thing were necessary.

Will custom tags really solve this problem? Probably not. Here's a possible <foreach> tag.

<foreach item="isp" list="isps">
  The next name is <jsp:getProperty name="isp" property="name"/> <br>
</foreach>
Which would a graphics artist prefer?

Problem #5: Useless Error Messages

JSP page syntax errors can cause surprisingly odd and useless error messages. This is due to the fact the page is transformed into a servlet and then compiled. Good JSP tools can help narrow down errors to likely syntax error locations, but even the best of tools will probably have problems making all error messages meaningful. Some errors will just be impossible for tools to diagnose, due to the transformation.

For example, assume a JSP page needs to set a title common across all pages. What's wrong with the following?

<% static String title = "Global title"; %>
Well, the Tomcat reference implementation for JSP says this is wrong:
work/%3A8080%2F/JC_0002ejspJC_jsp_1.java:70: Statement expected.
                static int count = 0;
                ^
This cryptic error is trying to say that scriptlets like the above are placed inside the _jspService() method and static variables aren't allowed inside methods. The syntax should be <%! %>. Page designers won't recognize this error, and programmers likely won't either without looking at the generated source. Even the best tools probably won't be much help with errors such as these.

Assuming all the Java code could be moved out of the page, that still doesn't solve this problem. What's wrong with this expression that prints the value of count?

<% count %>
The Tomcat engine says:
work/8080/_0002ftest_0002ejsptest_jsp_0.java:56: Class count not found in
type declaration.
                 count 
                 ^
work/8080/_0002ftest_0002ejsptest_jsp_0.java:59: Invalid declaration.
                out.write("\r\n");
                         ^
In other words, there's an equal sign missing. It should be <%= count %>.

Because a template engine can operate directly on the template file without any "magical" translation to code, it's far easier to properly report errors. To use an analogy: When commands are typed into a command line Unix shell written in C, you don't want the shell to create a C program to execute the command. You want the shell to simply interpret the command and behave accordingly, with direct error messages when necessary.

Problem #6: Need a Compiler

JSP requires a compiler be shipped with the webserver. That's problematic, especially since Sun doesn't give away the tools.jar library containing their javac compiler. Web servers can package an outside vendor's compiler such as IBM's jikes; however such compilers generally don't work on all platforms and (being written in C++) aren't much help to a pure-Java web server. JSP has a pre-compile option that can help some here, although that's a less than elegant solution.

Problem #7: Wasted Space

JSP consumes extra hard drive space and extra memory space. For every 30K JSP file on the server there must be a corresponding larger-than-30K class file created. This essentially doubles the hard drive requirements to store JSP pages. Considering how easily a JSP file can <%@ include> a large data file for display, this becomes a real concern. Also, each JSP's class file data must be loaded into the server's memory, meaning the server may eventually store the entire JSP document tree in memory. A few JVMs have the ability to remove class file data from memory; however, the programmer generally has no control over the rules for reclaiming and for large sites the reclaiming probably won't be aggressive enough. With template engines there's no need to duplicate the page data into a second file, so hard drive space is spared. Template engines also give the programmer full control over how templates are cached in memory.

There are also some downsides to using a template engine:

Template Problem #1: No Specification

No specification exists for how a template engine should behave. However, it's interesting to note that this is far less important than with JSP because, unlike JSP, template engines demand nothing special of the web server -- any server supporting servlets supports template engines (including API 2.0 servers like Apache/JServ which can't fully support JSP)! Healthy competition for the best template engine design could actually spark innovation, especially assuming open source implementations that can leverage each other's ideas and code. As it stands now, WebMacro exists like Perl, a tool where the open source implementation is the specification.

Template Problem #2: Not Widely Known

Template engines aren't widely known. JSP has had a tremendous amount of marketing and has gained terrific mind share. Using template engines is a relatively unknown alternative technique.

Template Problem #3: Not Yet Tuned

Template engines have yet to be highly tuned. No performance numbers have been taken comparing template engine and JSP performance. Theoretically a well tuned implementations of a template engine should match a tuned implementation of JSP; however in the world today, considering the effort third party vendors have given to JSP so far, the odds are good that JSP implementations are better tuned.

The Role of JSP

So is there a place for JSP in the future? Certainly. JSP is entirely relevant if what you're trying to do is wean people off of ASP. There's an extremely strong argument for providing something familiar looking in a new environment. This was one of the big motivations behind the creation of JSP, and that shows from the name -- it's no coincidence "JSP" is just one letter off from "ASP".

Yet there's a difference between what's suitable to someone who is new to an environment, and what's actually the best way to use that environment.

JSP is going to turn out to be one of the most important Java technologies for convincing people to leave the ASP world in favor of Java -- and hence there's a strong business case for Sun supporting it, and for any Java booster to support it.

However, that doesn't make it the best solution for the Java platform. That makes it the Java solution that is most like the non-Java solution.


This is the first in a series of articles. To be notified when new articles are added to the site, subscribe here.

Care to comment on the article? Fire an email to talkback@servlets.com. Interesting comments may be posted unless you specify otherwise.

New: Read the follow-on to this article

 


Home   com.oreilly.servlet   Polls   Lists   
Engines   ISPs   Tools   Docs   Articles   Soapbox   Book

Copyright © 1999-2005 Jason Hunter

webmaster@servlets.com
Last updated: March 1, 2009