The Secret Life of JavaServer Pages
by Bear Bibeault

"How do I call a bean method from a Javascript onclick handler?"
"When I write to a file in my JSP, why does it appear on the server? I want to write to the client system!"
"Why does everyone tell me to use a servlet to send binary data to the browser? I wanna use a JSP!"

To those that frequent the JSP Forum of the JavaRanch Big Moose Saloon, these questions may appear hauntingly familiar as they are among some of the most recurring questions asked by new-comers to the Ranch and to JSP.

While these questions may seem somewhat unrelated to each other, they all have a similar root: a fundamental misconception of what JavaServer Pages (JSP) technology is, and of the life-cycle of a JSP page.

In this article, I hope to clarify what JSP is, how JSP pages work, and how understanding their life-cycle clears up the answers to questions such as those above, and many more.

What's it all about, Jasper?

One thing that JSP technology is not is a means to cause Java code to be executed as part of a web page on the client-side browser. That's what Applets are for.

It is also not a means to deploy stand-alone Java applications to a client system for local execution; that's the job of Java Web Start.

So what is JSP Technology?

Stripped down to its very core: JSP is a templating technology used to dynamically generate content for delivery to a client, usually a browser.

<cricket> <cricket> <cricket> ...

Hello?

Ohhhh-kay... let's try that again...

The Two County Clerks

A traditional web server actually has a pretty simple job. When a request (in the guise of an HTTP request) is made for a particular resource (most often an HTML page or image file), the web server responds (in the guise of an HTTP response) by reading the bytes of the requested resource and feeding them across the net to the requesting browser. Whatever is in the file is what gets delivered.

A templating engine on the other hand, uses the information in the requested resource, combined with data that it can garner from various resources, to dynamically generate the content to be delivered.

To illustrate this difference, let's imagine that you need to visit your local county tax office in order to straighten out what you think may be an error on your yearly property tax bill. In order to research the issue, you determine that you need two documents:

  1. The County Tax Rules Document
  2. The Property Assessment Document for your property

So you arrive at the Tax Office and determine which clerk to go to in order to obtain the County Tax Rules Document. You queue up into line, and when it comes your turn, you request a copy of the County Tax Rules Document.

The clerk responds by turning to his file cabinet stuffed with documents, retrieves one of those documents, places it on his copy machine, and hands you the results of the copy operation.

You walk away with a static document in your hands. The document is an identical copy of the document that was in the clerk's file cabinet with no interpretation. If you were to go back and ask for the document again, you would receive a copy exactly like the one that you just obtained. Anyone else who requests a copy of the document also receives a copy that is identical to the one that you have in your hands.

This first clerk operates in much the same manner as a traditional web server. Its primary job is to send, verbatim, the contents of a specific file on the server to the client upon request.

To obtain the second document — the Property Assessment document for your property — you visit another clerk. This clerk is a more capable worker, able to handle the complexities of creating a document for you that is more than a simple copy of an existing document; one that is customized with information specific to you (or as in this case, your property).

When your turn comes, you request a copy of a Property Assessment document for your property. Unlike, the previous document that you requested, this document requires that you also provide a means of uniquely identifying the property for which the document is to contain the assessment information. In this case, the uniquely identifying piece of information is the address of the property.

In response to your request, the clerk fetches a document from her file cabinet — much in the same manner that the first clerk did — but does not hand a copy of it directly to you. Rather, she also turns to another file cabinet and looks up the information specific to your property and lays it out on her desk.

She then makes a copy of the Property Assessment document that she fetched, and places it into her typewriter. As she does so you see that this is a document that is only partially filled in. It has lots of writing already on it — labels, lines, and other markings — but also contains lots of blanks where property-specific information should be. With deft fingers, and using the property information she retrieved for your specific property, she fills in those blanks with the appropriate data. For some of this information she turns to her calculator to compute the appropriate values to fill in using the information available to her.

When she is finished, she pulls the document from her typewriter and hands it to you. You walk away with a dynamic document in your hands.

This document differs from your first, static document in that it is tailored with information that is specific to your property. If you, or anyone else, were to request the exact same document, but supplied a different property address, the document's content would be different; tailored to the information appropriate for the property identified by the supplied address.

This second clerk operates in a similar fashion to the way that a templating engine such as a JSP container would operate. She generated a document tailored with specific data by starting with a source template and filling in information specific to a particular element in her "database". Similarly, a JSP container will take a source template, a JSP page, and using JSP markup within that page generate a dynamic document tailored with specific information.

So why would we want to use such templating technology when traditional web serving is so much more simple and straight-forward? Well, let's revisit the Tax Office...

A frugal, but uninsightful, taxpayer might argue that the County is wasting tax dollars by operating in this fashion. After all, would it not be cheaper, not to mention faster, just to have a low-level clerk simply look up and hand you a Property Assessment document already filled with your property's information? Could they not save salary dollars by hiring less-capable clerks who only have to know how to use a copy machine rather than a much more complicated typewriter?

Of course, the answer is no. If the Tax Office were to attempt to operate in that fashion, then they would need to have a pre-filled Property Assessment document for each and every property in the county. And what about other documents which are also property-specific? Not only would the Tax Office need to hire a whole gaggle of clerks to create those documents in the first place, they would also need to store those documents causing them to incur rental costs for the enormous amount of space that would be necessary.

And what about when the information on the various properties changes? Each change would mean throwing away all of the pre-created documents and typing them in all over again. Expensive, inefficient and wasteful!

So with even a cursory examination, we see that the Tax Office is making good use of our tax dollars by storing one template for each document type, and filling that template in with up-to-date information at the time that the document is requested.

This is why technologies such as JSP make so much sense. By creating dynamic documents on-the-fly with real-time data, there is no need to anticipate and store every possible document variation that might ever be requested, and the information in those documents can always be kept up-to-date by simply keeping a single instance of the data current.

Anatomy of a JSP

Like the fill-in-the-blanks form of our plucky county clerk, a JSP page is a template for creating the end document. The template contains both static and dynamic elements. The static elements are copied verbatim to become part of the document, while the dynamic elements are interpreted at request time in order to "fill in the blanks" with appropriate data.

Let's take a look at a simple JSP page, with highlighting to point out the various types of elements:

 1<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> 
 2 
 3<html> 
 4  <head> 
 5    <title>A simple JSP page</title> 
 6  </head> 
 7 
 8  <body> 
 9    Testing  
10    <c:forEach begin="1" end="3" var="n"> 
11      ${n}  
12    </c:forEach> 
13    ! 
14  </body> 
15</html> 
    

The background colors in this code example are keyed as follows:

line numbers These numbers at the beginning of the lines are not part of the JSP file, but are shown in this example so that we can easily refer to specific parts of the example in the remaining sections.
dynamic elements

Dynamic elements are markup elements that tell the JSP engine how to interpret the page and what actions to take in order to "fill in the blanks" with dynamic data.

Dynamic elements use varying notation depending upon what category of action they represent. Only a small handful of these dynamic markup types are represented in this simple JSP example1.

template text
"invisible" template text

Characters which are not part of a dynamic element within a JSP are considered part of the final document and will become part of the document exactly as written in the JSP file. These static elements are collectively termed template text.

Note that even the "invisible" line terminators at the end of each line are considered template text and will become part of the final document; even when the rest of the line is empty or composed entirely of dynamic elements.

1 This article is most emphatically not meant to be a tutorial on JSP and all its capabilities. That would take a very long article indeed. In fact, that's why entire books are devoted to this subject. The facets of JSP discussed within this article extend to only those needed to illustrate the concepts being addressed.

Looking at this example we see that, except for dynamic elements on lines 1, 10, 11 and 12, that the page consists mostly of template text. This is typical of many JSP pages.

All of that template text will be sent, verbatim, to the final document (line breaks included), while the dynamic elements will be interpreted.

On line 1, we see a dynamic element that is an example of a JSP directive. This particular directive instructs the JSP engine to find a custom action library2 using the specified URI, and to load it for the scope of the page using the XML namespace of c. This element produces no output to the final document.

2 You may be more accustomed to the term tag rather than action in this context, but as of the JSP 2.0 specification, what was formerly known as standard and custom tags are now termed the standard and custom actions. A perhaps unfortunate naming collision as many web application frameworks, such as Struts, use the term "action" to mean a unit of execution.

On lines 10 and 12 we see a custom action from that library in use. The library in this example is the JSTL set of core actions, and the action employed is the forEach action which causes its body to be iterated over based upon its attribute settings. This element also causes no output in the final document.

On line 11 we see another dynamic element, in this case an Expression Language (EL) expression which causes its evaluated value to be emitted to the final document.

Visiting this page (when hosted on an appropriate JSP 2.0 server) results in the following simple display:

While that's not very impressive or even interesting, what is interesting is examining the final document as sent to the browser. Viewing the source of the response document shows us the specific text of the final document as it was sent to the browser. (This, by the way, is the first debugging step you should take when a JSP is not producing the output you expected when displayed in a browser. Examining the rendered HTML document can usually quickly tell you whether the problem lies in your HTML formatting or elsewhere).

Performing a 'View Source' in the browser shows us:

 1 
 2 
 3<html> 
 4  <head> 
 5  	<title>A simple JSP page</title> 
 6  </head> 
 7 
 8  <body> 
 9    Testing  
10     
11      1  
12     
13      2  
14     
15      3  
16     
17    ! 
18  </body> 
19</html> 
  

There are a number of intriguing details to note about this final document. Firstly we can see that all of the template text has been dutifully reproduced in this final document. We can also see that none of the dynamic elements remain. Those elements were interpreted on the server and were not written to the final document. And we can see that the EL expression element from line 11 of our JSP template caused dynamic data, in this case the numerals 1, 2 and 3, to be placed into the final document.

Also interesting to note is that all of the template text, including the line terminators, has made its way into the final document (resulting in a lot of the "blank lines" that are seen in that document). This is one of the reasons that JSP is a rather unsuitable technology for delivering anything but text content to the browser.

JSP technology was designed as a templating mechanism for text content, not binary content. Its underlying mechanisms assume that the document begin created is text, and details such as the dutiful emission of all template text including leading and trailing spaces, as well as line terminators makes JSP a problematic technology for delivering content whose structure would be corrupted by the addition of these template characters.

Moreover, there are even types of text documents that are not well-suited to JSP. RTF (Rich Text Format) is a good example. RTF is very sensitive to the placement of line terminators and white-space characters. Put one in the wrong place, and "poof!", your formatting goes right out the window!

Therefore, JSP's suitability is not only limited to the generation of text documents, but to text documents of a format that is at least fairly insensitive to the placement of white-space (including line terminators). This makes JSP best-suited for documents in HTML and XML formats, where interstitial white-space is relatively meaningless.

OK, that's all well and good. But how did all that magic happen "under the hood"? The next section takes us through a day in the life of a JSP page. Assuming that by "day", we mean a request-response cycle.

The Life and Times of a JSP

As we have seen, a JSP page is merely a text file containing elements, both static and dynamic, that define a template for a document. When a request for that document is made, the JSP engine interprets the JSP template and formats an HTML document that gets sent to the browser. How does it do that?

In a nutshell, the JSP Engine turns your JSP template into a servlet. Whenever you request the document represented by the JSP, the engine runs that generated servlet in order to create the HTML document to be sent to the browser.

But let's take a little bit of a closer look at the steps that need to be taken in order to make that happen.

Let's assume that we have just written the simple sample JSP page from the previous section. We place it on the server in a place accessible to the JSP engine (web application setup is beyond the scope of this article; see the documentation for your JSP container), and enter the appropriate URL that references the JSP page.

The JSP Engine receives the request for the JSP page and first checks to see if the JSP has been referenced before. If not, it needs to pass the JSP through a translation phase. This is the phase in which the text of your JSP page is parsed, and a servlet is generated on behalf of the JSP. Most containers will actually generate a text .java file and place it in the file system of the server. This java file is compiled and the resulting servlet class, also usually written to disk, is loaded by the engine's class loader and is registered as a servlet in the enclosing web application.

The first time that your JSP is requested, obviously the translation phase will not have occurred, and so the translation phase will be triggered. However, the translation phase will also be automatically triggered if the JSP has been changed since the last time it was translated.

In either case, the result is a servlet class, loaded and ready to run in the execution phase.

In the execution phase, the servlet is executed by calling its service method which results in executing the code that the JSP engine generated on behalf of your JSP. This results in "writing" an HTML document which is then sent to the browser.

When next the JSP is requested, the JSP engine merely needs to execute the JSP's servlet for each request (assuming that the JSP has not been changed in the meantime).

The following diagram shows a simplified overview of this process:

Armed with this knowledge, let's go back and re-examine the questions posed at the beginning of this article. The answers should now be readily apparent and understandable.

"How do I call a bean method from a Javascript onclick handler?"

Obviously, you can't. As we have seen, the JSP executes on the server (or rather, the JSP's servlet executes) and formats an HTML document that is sent to the browser. The browser, which then interprets the HTML and any Javascript in the document (which, from the point of view of the JSP engine is just template text along with the rest of the HTML markup) is completely unaware that the document it has received was generated via a dynamic mechanism.

It's as if the second clerk of our Tax Office analogy operated behind an opaque screen. You asked for a document, and you got handed one that contains the information you requested. Whether the clerk merely made a copy of a static document, used her typewriter to fill in the blanks (putting aside visual differences that could clue you in), or pulled the document out of a magic top hat, is a mystery to you. All you know is that you have the document you requested, and any further interaction with the clerk would have to be in the form of another document request.

"When I write to a file in my JSP, why does it appear on the server? I want to write to the client system!"

This is an easy one. We know that the servlet generated on behalf of the JSP executes on the server. So any file operations performed by that servlet will take place on the server's file system.

"Why does everyone tell me to use a servlet to send binary data to the browser? I wanna use a JSP!"

Since we know that the JSP engine expects to be generating text data (the underlying input/output mechanisms are text-oriented) and that all template text in a JSP including white-space is emitted as part of the document, we can see that using a JSP to emit binary data (or even strictly formatted text data) whose structure would be corrupted by such extraneous characters is a rather foolish thing to try to do.

A JSP Exposed!

Before we close, let's take some of the clothes off of our sample JSP and take a small peek at its innards to help illustrate some of the previous points.

The following code sample is the portion of the servlet generated on behalf of our sample JSP that emits the majority of the output for the document: (examining the entire servlet source code is beyond the scope of this article and would be very container-specific — the code sample shown here was generated by Tomcat 5.0.28)

      out = pageContext.getOut();
      _jspx_out = out;

      out.write("\r\n");
      out.write("\r\n");
      out.write("<html>\r\n");
      out.write("  <head>\r\n");
      out.write("    <title>A simple JSP page</title>\r\n");
      out.write("  </head>\r\n");
      out.write("\r\n");
      out.write("  <body>\r\n");
      out.write("    Testing \r\n");
      out.write("    ");
      if (_jspx_meth_c_forEach_0(_jspx_page_context))
        return;
      out.write("\r\n");
      out.write("    !\r\n");
      out.write("  </body>\r\n");
      out.write("</html>\r\n");
      out.write("\r\n");
  

Note how the template text ends up begin defined within string literals, and that all of the template text, line terminators and all, is dutifully emitted.

Summary

So what have we learned? Hopefully, at least that:

Peace out.