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:
- The County Tax Rules Document
- 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:
-
JSP is a templating technology best-suited to the delivery of dynamic
text documents in a format that is white-space agnostic.
-
Template text within a JSP page (which is anything that is not a
dynamic element), to include all white-space and line terminators,
becomes part of the final document.
-
All dynamic elements in a JSP are interpreted on the server and once
the document is sent to the client, no further dynamic interaction is
possible (short of requesting the same or another document).
Peace out.