You are on page 1of 34

JSP Architecture

12
This chapter will examine a variety of ways to architect a system with JavaServer Pages, Servlets, and
JavaBeans. We will see a series of different architectures, each a development of the one before. The
diagram below shows this process in outline; the individual parts of the diagram will be explained in
turn later in the chapter.
Chapter 12

Business Business
JSP JSP Worker bean
Processing Processing

Business
Servlet JSP Worker bean Delelgate
Processing

Servlet

checkout head
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
header -.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
body

footer checkout footer


-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.

cart header.html
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
header -.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
body

footer cart footer.html


-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.

worker bean business


delegate

Enterprise back-end
Java
Beans resource

When Sun introduced Java ServerPages, some were quick to claim that Servlets had been replaced as
the preferred request handling mechanism in web-enabled enterprise architectures. Although JSP is a
key component of the Java 2 Platform Enterprise Edition (J2EE) specification, serving as the preferred
request handler and response mechanism, we must investigate further to understand its relationship with
Servlets. For all the latest information on J2EE, including documentation relating to some of the issues
discussed in this chapter, please refer to http://java.sun.com/j2ee.

Other sections of this book explain the implementation details of JSP source translation and compilation
into a Servlet. Understanding that JSP is built on top of the Servlet API, and utilizes Servlet semantics,
raises some interesting questions. Should we no longer develop standalone Servlets in our web-enabled
systems? Is there some way to combine Servlets and JSPs? If so, where do we place our Java code? Are
there any other components involved in the request processing, such as JavaBeans? If so, where do they
fit into the architecture and what type of role do they fulfill?

It is important to understand that, although JSP technology will be a powerful successor to basic
Servlets, they have an evolutionary relationship and can be used in a cooperative and complementary
manner.

316
JSP Architecture

Given this premise, we will investigate how these two technologies, each a Java Standard Extension, can
be used co-operatively along with other components, such as JavaBeans, to create Java-based web-
enabled systems. We will examine architectural issues as they relate to JSP and Servlets and discuss
some effective designs while looking at the tradeoffs of each. Before jumping directly into a discussion
of specific architectures, though, we will briefly examine the need to develop a variety of architectures.

Code Factoring and Role Separation


One of the main reasons why the Java Server Pages technology has evolved into what it is today (and
it's still evolving) is the overwhelming technical need to simplify application design by separating
dynamic content from static template display data. The foundation for JSP was laid down with the initial
development of the Java Web Server from Sun, which utilized page compilation and focused on
embedding HTML inside Java code. As applications came to be based more on business objects and n-
tier architectures, the focus changed to separating HTML from Java code, while still maintaining the
integrity and flexibility the technology provided.

In Chapter 5 we saw how beans and objects can be bound to different contexts just by defining a certain
scope. Good application design builds on this idea and tries to separate the objects, the presentation and
the manipulation of the objects into distinct, distinguishable layers.

Another benefit of utilizing JSP is that it allows us to more cleanly separate the roles of a web
production/HTML designer individual from a software developer. Remember that a common
development scenario with Servlets was to embed the HTML presentation markup within the Java code
of the Servlet itself, which can be troublesome. In our discussion, we will consider the Servlet solely as a
container for Java code, while our entire HTML presentation template is encapsulated within a JSP
source page. The question then arises as to how much Java code should remain embedded within our
JSP source pages, and if it is taken out of the JSP source page, where should it reside?

Let's investigate this further. On any web-based project, multiple roles and responsibilities will exist. For
example, an individual who designs HTML pages fulfills a web production role while someone who
writes software in the Java programming language fulfills a software development role.

On small-scale projects these roles might be filled by the same individual, or two individuals working
closely together. On a larger project, they will likely be filled by multiple individuals, who might not
have overlapping skill sets, and are less productive if made too dependent on the workflow of the other.

If code that could be factored out to a mediating Servlet is included instead within HTML markup, then
the potential exists for individuals in the software development role and those in the web production
role to become more dependent than necessary on the progress and workflow of the other. Such
dependencies may create a more error-prone environment, where inadvertent changes to code by other
team members become more common.

This gives us some insight into one reason why we continue to develop basic Servlets: they are an
appropriate container for our common Java code that has been factored out of our JSP pages, giving our
software development team an area of focus that is as loosely coupled to our JSP pages as possible.
Certainly, there will be a need for these same individuals to work with the JSP source pages, but the
dependency is reduced, and these pages become the focus of the web-production team instead. Of
course, if the same individual fulfills both roles, as is typical on a smaller project, such dependencies are
not a major concern.

317
Chapter 12

So, we should try to minimize the Java code that we include within our JSP page, in order to uphold this
cleaner separation of developer roles. As we have discussed, some of this Java code is appropriately
factored to a mediating Servlet. Code that is common to multiple requests, such as authentication, is a
good candidate for a mediating Servlet. Such code is included in one place, the Servlet, instead of
potentially being cut and pasted into multiple JSPs.

We will also want to remove much of our business logic and data access code from our JSP page and
encapsulate it within JavaBeans, called worker or helper beans. We start to see a pattern of code
movement from our JSP into two areas: a Servlet (or JSP) that sits in front of the main JSP, and
JavaBeans that sit in back. We refer to this common pattern as 'Factor Forward-Factor Back', as shown
in the figure below:

Factor Forward-Factor Back

--00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- --00--00--00--00--00--


00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
00--00--00--00--00-- --XX--XX--XX--XX--XX--XX- 00--00--00--00--00--
--XX--XX--XX--XX--XX--XX-

servlet.java source.jsp workerbean.java

Another way to think about where code should be localized and encapsulated is that
our JSP page should reveal as little as possible of our Java code implementation
details.

Rather, the page should communicate our intent by revealing the delegating messages we send to
worker beans, instructing them to get state from a model, or to complete some business processing.

Redirecting and Forwarding


Redirecting and forwarding requests in JSPs and Servlets takes place often, and it is important to
understand the subtle difference between these two mechanisms even though they achieve the same
goal (that is, a client asks for a resource on the server and a different resource is served to it):

❑ When a Servlet or JSP resource chooses to redirect the client (using a


response.sendRedirect(url)) the request object does not reach the second resource
directly since the underlying implementation is an HTTP redirect. The server sends an HTTP
302 message back to the client telling it that the resource has moved to another URL, and that
the client should access it there.
The bottom line is that the lifecycle of the initial request object that was accessed in the first
JSP terminates with the end of the service method in the first JSP, or with the reply from
the server.

318
JSP Architecture

❑ In a forward mechanism the request object is forwarded to the second resource, thus
maintaining any object bindings to the request and its state, without a round trip to the client
on the network.
This allows the first JSP to do some work internally and then send information to the second
JSP asking it to do its bit. (Servlets used a chaining mechanism to do this). See Chapter 5 to
get a clearer picture of scope.

JSPs and Servlets can utilize the forwarding mechanism to delegate tasks amongst themselves, in the
process of separating dynamic and static content.

Now, let's investigate how we build these systems.

Architectures
Before discussing specific architectures that we can use to build systems with Servlets and JSP, it is
worth mentioning two basic ways of using the JSP technology. Each of the architectures discussed in this
chapter will be based on one of these approaches:

❑ The first method is referred to here as the page-centric (or Client-Server) approach. This
approach involves request invocations being made directly to JSP page.
❑ In the second method, the dispatcher (or N-tier) approach, a basic Servlet or JSP acts as a
mediator or controller, delegating requests to JSP pages and JavaBeans.

We will examine these approaches in light of a simple example, which will evolve to satisfy the
requirements of various scenarios. The initial scenario involves providing a web interface for guessing
statistics about a soon-to-be-born baby. The guesses are stored, and can be reviewed later by the
parents, to see who has guessed the closest. As the requirement scenarios become more sophisticated,
such as adding the desire for a persistence mechanism, the solution scenarios will become more
sophisticated, as well. Thus, our example will evolve and we will gain an understanding of how the
various architectures that we discuss will help us build a system that satisfies these requirements in an
elegant and effective manner.

Let's look at some examples of architectures that utilize these approaches and discuss the tradeoffs and
usage.

The "Page-Centric" Approach


We start by looking at architectures based on the page-centric or client-server approach. We will look at
the page-view and page-view with bean architectures.

Applications built using a client-server approach have been around for some time; they consist of one or
more application programs running on client machines, and connecting to a server-based application to
work. (A good example would be a PowerBuilder or Oracle Forms based system.) CGIs and pre-Servlet
applications were generally based on this simple 2-tier model, and with the introduction of Servlets, 2-
tier applications could also be created in Java.

319
Chapter 12

This model allows JSPs or Servlets direct access to some resource like a database or legacy application
to service a client's request: the early JSP specifications termed this a "Model 1" programming approach.
The JSP page is where the incoming request is intercepted processed, and the response sent back to the
client; JSPs only differed from Servlets in this scenario by providing cleaner code, and separating code
from the content by placing data access in beans.

This is illustrated in the figure below.

Browser on client Server

Request/Response
JSP or servlets
Client requests are
intercepted here

Browser on client

<<uses or instantiates>>

EJB
Java Beans Database
Browser on client

The advantage of such an approach is that it is simple to program, and allows the page author to
generate dynamic content easily, based upon the request and the state of the resources.

However this architecture does not scale up well for a large number of simultaneous clients since there
would be a significant amount of request processing to be performed, and each request must establish or
share a potentially scarce/expensive connection to the resource in question. (A good example would be
JDBC connections in servlets or JSPs and the need for connection pools.)

Indiscriminate usage of this architecture usually leads to a significant amount of Java code embedded
within the JSP page. This may not seem to be much of a problem for Java developers but it is certainly
an issue if the JSP pages are maintained by designers: the code tends to get in the designer's way, and
you run the risk of your code becoming corrupted when others are tweaking the look and feel.

Of course, it is not necessary to use JSPs, to separate code and presentation in servlets: the use of
templates is popular. There are a lot of toolkits that facilitate this, such as ATP
(http://www.winwinsoft.com/atp/), MindTemplate
(http://www.mindbright.se/english/technology/products/mindtemplate), or the more
popular WebMacro (http://www.webmacro.org/), FreeMarker
(http://freemarker.sourceforge.net), and PreparedHtml
(http://www.its.washington.edu/~garth/prep.html)

320
JSP Architecture

Page-View
This basic architecture involves direct request invocations to a server page with embedded Java code,
and markup tags which dynamically generate output for substitution within the HTML.

This approach has many benefits. It is very easy to get started and is a low-overhead approach from a
development standpoint. All of the Java code may be embedded within the HTML, so changes are
confined to a limited area, reducing complexity. The figure below shows the architecture visually.

Request

Business
JSP Processing
Response

The big trade-off here is in the level of sophistication. As the scale of the system grows, some limitations
of this approach surface, such as including too much business logic in the page instead of factoring
forward to a mediating Servlet, or factoring back to a worker bean. As we discussed earlier, utilizing a
Servlet and helper beans allow us to separate developer roles more cleanly, and improves the potential
for code reuse. Let's start with a fairly simple example JSP page that follows this model, handling
requests directly and including all the Java code within the JSP source page.

We begin with a basic description of the example application. All the examples in this chapter use the
JSWDK version 1.0.1, using the default web application directory structure for simplicity. Thus, the JSP
and HTML source are under the <jswdk-root>/examples/jsp/ subdirectory and the Servlet (see
later) is under <jswdk-root>/examples/WEB-INF/servlets.

The user interface is shown below:

The HTML code for this page, BabyGame1.html, is stored in <jswdk-


root>/examples/jsp/pageview/ and includes a form that prompts a user for selections. The user is
asked to make some guesses about the statistics of a baby to be born in the near future. The HTML code
is as follows:

321
Chapter 12

<html>
<head>
<title>Baby Game</title>
</head>
<body bgcolor="#FFFFFF">
<form method="post" action="BabyGame1.jsp" name="">
<center>
<h3>
Baby Game</h3></center>

<center>
<br>
<table BORDER COLS=5 WIDTH="75%" >
<caption>Please enter your own name:
<input type="text" name="guesser"></caption>

<tr>

<td>
<br><input type="radio" name="gender" value="Female" checked>Female
<p><input type="radio" name="gender" value="Male">Male
<p></td>

<td><font size=-1>Please choose a date:</font>


<p>Month: <select name="month">
<option value="January">January</option>
<option value="February">February</option>
...
<option value="December">December</option>
<br></select>
<p>Day: <select name="day">
<option value="1">1</option>
<option value="2">2</option>
...
<option value="31">31</option>

<br></select>
<p>&nbsp;</td>

<td><font size=-1>Please choose a weight:</font>


<p>Pounds: <select name="pounds">
<option value="5">5</option>
<option value="6">6</option>
...
<option value="12">12</option>
<br></select>
<p>Ounces: <select name="ounces">
<option value="1">1</option>
<option value="2">2</option>
...
<option value="15">15</option>

<br></select>
<p>&nbsp;</td>

322
JSP Architecture

<td><font size=-1>Please choose a length:</font>


<p>Inches: <select name="length">

<option value="14">14</option>
<option value="15">15</option>
...
<option value="25">25</option>

</select><p>&nbsp;<p>&nbsp;<p>&nbsp;</td>

</tr>
</table>
</center>

<br>&nbsp;
<center>
<p><input type="submit" name="submit" value="Make Guess">
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
<input type="reset" name="reset" value="Reset">
</center>

<br></form>
</body>
</html>

This HTML form will POST the choices to our JSP, which is shown in source form below
(BabyGame1.jsp, stored in directory <jswdk-root>/examples/jsp/pageview/). These choices
are then stored and displayed by our simple JSP, which has handled the request directly.

The resulting display looks like this:

The first part of BabyGame1.jsp is responsible for extracting the values from each of the request
parameters and populating the state of the JSP. The name of the individual making the guess is
contained in a request parameter called guesser. Each of the statistics about the baby is stored in a
request parameter with an intuitive name, such as gender, length, etc.

<HTML>
<HEAD><TITLE>Baby Game - Your Guesses</TITLE></HEAD>
<BODY bgcolor=FFFFFF>
<%@ page language="java" import="java.util.*,java.io.*" buffer="8k" %>

<%
String guesser = request.getParameter("guesser");

String gender = request.getParameter("gender");

String pounds = request.getParameter("pounds");


String ounces = request.getParameter("ounces");

323
Chapter 12

String month = request.getParameter("month");


String day = request.getParameter("day");

String length = request.getParameter("length");

After this task is complete, there is a validation check on the data. If the validation is unsuccessful, then
the JSP completes its processing by sending the user an appropriate message:

if(guesser == null || gender == null || pounds == null || ounces == null


|| month == null || day == null || length == null)
{ %>
<br> There where some choices that were not selected.<br><br>
Sorry, but you must complete all selections to play.<br>
<font size=-1>(Please hit the browser 'back' button to continue)</font><br>
<%}

Otherwise, upon successful validation of the request parameters, the data is stored to disk and a table is
generated using the JSP state, which corresponds to the user's guesses. The guesses are stored within a
java.util.Properties object, which, for example purposes, is flattened to a text file in the root
directory of the JSP run time engine, in this case the JSWDK root directory. The name of the text file
corresponds to the name of the guesser, which was provided in the HTML form. One could easily
imagine an even more basic example where the data was merely displayed but not stored. Such an
example would differ only in that the storage code in BabyGame1.jsp would be omitted:

else
{
//Store guess info and display to user
Properties p = new Properties();
p.put("guesser", guesser);
p.put("gender", gender);
p.put("pounds", pounds);
p.put("ounces", ounces);
p.put("month", month);
p.put("day", day);
p.put("length", length);

FileOutputStream outer = new FileOutputStream(guesser);


p.save(outer, "Baby Game -- "+guesser+"'s guesses");
outer.flush();
outer.close();

%>

<br>
<%= guesser %>, your choices have been stored.<br> Here they are:<br>
<table BORDER COLS=5 WIDTH="75%" >
<caption></caption>

<tr>

<td> <%= gender %>


</td>
<td>

324
JSP Architecture

<%= pounds %> lbs <%= ounces %> oz


</td>
<td>
<%= month %> <%= day %>
</td>
<td>
<%= length %> inches
</td>

</tr>
</table>

<br>
<%}
%>
</BODY>
</HTML>

This JSP certainly was easy to build and is well suited to handling such simple needs. It is getting quite
cluttered with Java code, though, and its processing requirements are extremely simplistic. More
sophisticated business rules and data access code would require much more Java within the JSP and the
source would become unwieldy quickly as it grows. Additionally, we are limited to mostly "cut-and-
paste" reuse, which means duplicate code and a more error-prone environment that is harder to
maintain and debug.

In order to reduce the clutter of the current example and to provide a cleaner environment for future
growth, we will look at another 'Page-Centric' architecture called 'Page-View with Bean' in the next
section.

Page-View with Bean


This pattern is used when the Page-View architecture becomes too cluttered with business-related code
and data access code. The Baby Game example now evolves into a more sophisticated design, as shown
in the figure below.

Request

Business
JSP Worker bean
Processing
Response

The modified JSP source page, <jswdk-root>/examples/jsp/pageviewwithbean/


BabyGame1.jsp, is shown below, followed by the worker bean that works in tandem with the modified
JSP in order to process the request. The HTML for the initial game interface remains unchanged. The
resulting display to the user from the JSP is basically unchanged from that of the previous 'Page-View'
example:

325
Chapter 12

<HTML>
<HEAD><TITLE>Baby Game - Your Guesses</TITLE></HEAD>
<BODY bgcolor=FFFFFF>
<%@ page language="java" buffer="8k" %>
<jsp:useBean id="worker1" class="examples.pageviewwithbean.BabyGameWorker1"
scope="request" />

<%-- Populate the JavaBean properties from the Request parameters. --%>
<%-- The semantics of the '*' wildcard is to copy all similarly-named --%>
<%-- Request parameters into worker1 properties. --%>
<jsp:setProperty name="worker1" property="*" />

<%
if(worker1.getGuesser == null || worker1.getGender() == null ||
worker1.getPounds() == null || worker1.getOunces() == null ||
worker1.getMonth() == null || worker1.getDay() == null ||
worker1.getLength() == null)
{ %>
<br> There where some choices that were not selected.<br><br>
Sorry, but you must complete all selections to play.<br>
<font size=-1>(Please hit the browser 'back' button to continue)</font><br>
<%}
else
{
worker1.store();
%>

<br>
<jsp:getProperty name="worker1" property="guesser" />, your choices have
been stored.<br> Here they are:<br>
<table BORDER COLS=5 WIDTH="75%" >
<caption></caption>

<tr>

<td> <jsp:getProperty name="worker1" property="gender" />


</td>
<td>
<jsp:getProperty name="worker1" property="pounds" /> lbs
<jsp:getProperty name="worker1" property="ounces" /> oz
</td>
<td>
<jsp:getProperty name="worker1" property="month" />
<jsp:getProperty name="worker1" property="day" />
</td>
<td>
<jsp:getProperty name="worker1" property="length" /> inches
</td>

</tr>
</table>

326
JSP Architecture

<br>
<%}
%>
</BODY>
</HTML>

The source for the worker bean, BabyGameWorker1, is as follows:

package examples;

import java.io.*;
import java.util.Properties;

public class BabyGameWorker1


{
private Properties p = new Properties();

public String getGuesser() {


return(String)p.get("guesser");
}

public void setGuesser(String aString) {


p.put("guesser", aString);
}

// And similar "get" and "set" methods for Gender, Pounds, Ounces, Month,
// Day, Length, and File.

public Properties getProperties() {


return p;
}

public void store() throws IOException {


FileOutputStream outer = new FileOutputStream((String)p.get("guesser"));
p.save(outer, "Baby Game -- "+p.get("guesser")+"'s guesses");
outer.flush();
outer.close();

We see in these two listings that the Java code representing the business logic and simple data storage
implementation has migrated from the JSP to the JavaBean worker. This refactoring leaves a much
cleaner JSP with limited Java code, which can be comfortably owned by an individual in a web-
production role, since it encapsulates mostly markup tags.

Additionally, a less technical individual could be provided with a property sheet for the JavaBean
workers, providing a listing of properties that are made available to the JSP page by the particular
worker bean, and the desired property may simply be plugged into the JSP getProperty action via the
markup tag in order to obtain the attribute value. An example of a potential property sheet is shown
below. Additionally, once a convention and format were agreed upon, an automated tool could be
created to interrogate all JavaBeans of interest and generate property sheets automatically.

327
Chapter 12

JavaBean Name:

examples.pageviewwithbean.BabyGameWorker1

Properties:

gender
ounces
pounds
guesser
day
length
month

Recommended Scope:

request

Template code to include in JSP code:

<jsp:useBean id="name" class="fully.qualified.name" scope="validScope" />

Example usage:

<jsp:useBean id="worker1" class="examples.pageviewwithbean.BabyGameWorker1"


scope="request" />

<jsp:getProperty name="worker1" property="gender" />

Moreover, we now have created a bean that a software developer can own, such that functionality
may be refined and modified without the need for changes to the HTML or markup within the JSP
source page.

Another way to think about these changes is that we have created cleaner abstractions in our system
by replacing implementation with intent. In other words, we have taken a bunch of code from our JSP
source (the Java code that writes the guesses to a file on disk ), encapsulated it within a bean, and
replaced it with our intent, which is to store the data, worker1.store().

Looping in JSP
So why might one choose to embed Java code in a JSP as opposed to using a predefined tag? An
example would be in order to loop through some data and format HTML for output.

Earlier versions of the JSP specification included a tag syntax for looping through indexed properties of
JavaBeans, so that no Java code was needed within the HTML for this purpose.

With the JSP software specification version 1.0, such tags were removed in favor of the creation of an
extensible custom tag markup mechanism that could be used for this purpose and much more.
Unfortunately, this custom tag functionality is first available in version 1.1 of the specification, and JSP
engines supporting the custom tag libraries are only now becoming available.

328
JSP Architecture

Further Refinements
After deploying this solution, our expectant family decides to limit the group of people who are able to
access the system, deciding to include only their family and friends. To this end, they decide to add an
authentication mechanism to their system so that each individual will have to provide proof of identity
before accessing the system.

If a simple authentication mechanism is added to the top of our JSP page and we want to ensure that
each JSP page is protected by this device, then we will need to add some code to each and every JSP
page to execute this authentication check. Whenever there is a duplication of code such as this, it is
beneficial to explore options for migrating the duplicated code to a common area.

In the previous example we "factored back," as we moved business logic and data-access Java code from
our JSP to our JavaBean, and in the next section we expand our example to "factor forward" into a
Servlet, continuing our efforts to minimize the amount of inline Java code in our JSPs.

The "Dispatcher" Approach


We now move on to look at architectures based on the dispatcher or "N-tiered" approach, where a
Servlet (or JSP) acts as a mediator or controller, delegating requests to JSP pages and JavaBeans. We will
look at the mediator-view, mediator-composite view, and service to workers architectures.

In an N-tier application, the server side of the architecture is broken up into multiple tiers, as illustrated
in the next figure:

Tier 1
Tier 0

Request/Response
JSP or servlets
Client requests are
intercepted here

Browser on client
Tier 2 Tier 3

EJB
Java Beans Database

Remote call
Tier 4

EJB Remote Object

In this case, the application is composed of multiple tiers, where the middle tier, the JSP, interacts
with the back end resources via another object or Enterprise JavaBeans component. The Enterprise
JavaBeans server and the EJB provide managed access to resources, support transactions and access
to underlying security mechanisms, thus addressing the resource sharing and performance issues of
the 2-tier approach. This is the programming model supported by the Java 2 Enterprise Edition
(J2EE) platform.

329
Chapter 12

The first step in N-tiered application design should be identifying the correct objects and their
interactions, in other words, object modeling. This is the part where class diagrams and tools like
Rational Rose (http://www.rational.com) step in for architects. Quite often a line has to be drawn as to
what objects need to be modeled: being over zealous can cause unnecessary complexity. If you get this
part right, you're half way there!

The second part is identifying the JSPs or Servlets. As a rule of thumb, these should be divided into two
categories, depending on the role they play, often called "web components" in the J2EE terminology

❑ Front end JSPs or Servlets that manage application flow and business logic evaluation. This is
where a lot of method invocation on the objects, or usage of EJBs, can be coded. They are not
responsible for any presentation, and act as a point to intercept the HTTP requests coming
from the users.Theyprovide a single entry point to an application, simplifying security
management and making application state easier to maintain.
❑ Presentation JSPs that generate HTML (or even XML), with their main purpose in life being
presentation of dynamic content. They contain only presentation and rendering logic.

The figure below shows the relationship between these two categories. The front-end component
accepts a request, and then determines the appropriate presentation component to forward it to. The
presentation component then processes the request and returns the response to another front
component or directly back to the user:

Alternative response
path
Presentation
specific JSP

Request Servlets or JSPs Response Presentation


Client requests are intercepted
Response specific JSP
here

Browser on client

Presentation
specific Servlet

Sometimes this distinction is hard to maintain, but the clearer the distinction, the
cleaner the design.

These categories are analogous to the Model-View design pattern, where the front-end component is
the model and the presentation component the view. This approach was referred to as the "Model 2"
programming model in earlier releases of the JSP specifications. It differs from Model 1 essentially in
the location at which the bulk of the request processing is performed. The figure below shows the
Model 2 approach:

330
JSP Architecture

Server

Servlets or JSPs
Client requests are intercepted
here
<<Controller>> <<uses/Instantiates>>
Request

EJB
<<Forward>> Database
Java Beans

Response
Browser on client Presentation <<uses/Instantiates>>
specific JSP
Only responses to client
<<Views>>

In this approach, JSPs are used to generate the presentation layer, and either JSPs or Servlets to perform
process-intensive tasks. The front-end component acts as the controller and is in charge of the request
processing and the creation of any beans or objects used by the presentation JSP, as well as deciding,
depending on the user's actions, which JSP to forward the request to. There is no processing logic within
the presentation JSP itself: it is simply responsible for retrieving any objects or beans that may have
been previously created by the Servlet, and extracting the dynamic content for insertion within static
templates.

Instead of writing Servlets for the front-end components you can choose, if you wish, to use a JSP that
contains only code and doesn't have any presentation responsibilities. Whichever option is used (and in
this chapter we only use Servlets in this role), this approach typically results in the cleanest separation of
presentation from content, leading to delineation of the roles and responsibilities of the developers and
page designers, especially in complex applications.

Beans that are used by JSPs are not the same as Enterprise JavaBeans (EJBs), but are usually
simple classes that serve as data wrappers to encapsulate information. They have simple get and set
methods for each bean property .The properties further correspond by name to the HTML variables
on the screen. This allows the bean properties to be set dynamically by the jsp:usebean tag
without doing an individual request.getParameter(parametername) on the request
object. See Chapter 4 for bean usage.

Mediator-View
Factoring common services, such as authentication out to a mediating Servlet allows us to remove
potential duplication from our JSP pages. The code below is an example of a Servlet that provides us
with central forwarding control for our game system, and includes a simple authentication check that
will be reused across requests. A Bean could be used for this purpose, but you would have to add the
same code to each page to perform the authentication checks. Instead, each request will be serviced by
the Servlet, which now includes our authentication code.

331
Chapter 12

The mediating Servlet, BabyGameServlet.java, is shown below. It is placed in the <jswdk-


root>/examples/WEB-INF/servlets/ directory:

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

public class BabyGameServlet extends HttpServlet {


public void doGet(HttpServletRequest request,
HttpServletResponse response) {
processRequest(request, response);
}

public void doPost(HttpServletRequest request,


HttpServletResponse response) {
processRequest(request, response);
}

protected void processRequest(HttpServletRequest request,


HttpServletResponse response) {

try {

// If we added actual authentication, this is where it would go


// For example purposes, if the parameters exist, we consider the
// auth successful.
if ((request.getParameter("guesser") != null)
&& (request.getParameter("password") != null)) {

// Note: Based on the successful authentication of this user we may


// want to consider writing something into the session state that
// signifies that this is the case. For example, if we wanted to
// limit direct access to certain JSP pages only to authenticated
// users, then we could include code that would check for this
// session state before allowing such access.

// In order to reuse this Servlet for multiple examples, we pass as


// a request parameter the resource name to which we dispatch our
// request.
getServletConfig().getServletContext()
.getRequestDispatcher(request.getParameter("dispatchto"))
.forward(request, response);
} else {
PrintWriter outy = response.getWriter();
outy.println("Unable to authenticate, please try again.");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

A new architectural pattern is emerging, with the mediating Servlet working with a JSP page and worker
bean pair to fulfill a service request. This 'Mediator-View' architecture is shown below, and illustrating
how each service is partitioned. The Servlet initially handles the request and delegates to a JSP software
page/worker bean combination. The JSP populates bean properties from the request parameters and
then uses the bean to prepare the data for presentation:

332
JSP Architecture

Request

Servlet JSP Worker bean service

Business
Delelgate
Processing

JSP Worker bean service

Response
JSP service

Other
Service Service
Provider

Continuing our attempts at creating the appropriate abstractions in our system, we shall consider how to
better partition our business logic and data access code, attempting to reduce the coupling among the
various parts of the system.

As we discussed, this request is handled first by a basic Servlet that dispatches to a JSP page for
formatting and display. The JSP is responsible for delegating the processing of business functionality to
a business delegate via a worker bean, which act as façades for the back-end resources. We call this
component a business delegate, because it is a client-side business abstraction used to complete the basic
business processing by abstracting out the code that deals with the back-end communication. The
worker beans might communicate through the business delegate with the back-end via Enterprise
JavaBeans components running in a scalable, load-balancing container.

In this case, we are able to decouple the EJB implementation from the JSP worker bean by moving the
EJB-related code, such as the code relating to JNDI lookup, into the business delegate. If we include our
EJB-related code in our worker beans, then we are closely coupling the bean to a specific underlying
implementation, and if this implementation is modified or changed we must make modifications to our
worker bean accordingly. So we have succeeded in creating abstractions that have reduced the coupling
among the distinct pieces of our system. We can see how the worker bean and the business delegate
reduce coupling between the client request and the ultimate back-end resource.

In other words, the public interfaces need not change even if the API to the underlying resource
changes. The worker beans can be combined with different JSP pages in order to provide different
views of the same underlying information. Also, the Servlet that initially handles each request, and is
responsible for authenticating each user, may restrict direct access to our JSP pages, an added security
mechanism. Once a user has been successfully authenticated, the Servlet might store certain
information in that user's session, and access to certain JSP pages might only be allowed to users
whose session state contained such that information. The mechanism could be made more fine
grained by including authorization information within this session state that would directly relate to
which pages a user may view.

333
Chapter 12

Our baby guessing game example will need to change, in order to adhere to this new design. The
HTML user interface needs to change only slightly, adding an input field for each user to enter a
password. The table caption in Babygame1.html is modified as shown below in order to add the
password input field, and the revised file, babygame2.html, is placed in <jswdk-
root>/examples/jsp/mediatorview/:

<caption>Please enter your userID:<input type="text" name="guesser">Please enter


your Password:<input type="password" name="password"></caption> >

The other change to the HTML is to change the hidden input field called dispatchto.
The Servlet uses this value to dispatch the request via the forward() method to the appropriate JSP,
and the value is supplied simply to allow for easy modification of these examples. In this case we
modify the value attribute to reference the JSP for our "Mediator-View" example, and the modified
line looks like this:

<input type="hidden" name="dispatchto" value="/jsp/mediatorview/BabyGame2.jsp">

We have already seen the next piece of the puzzle in the Servlet, which handles each request,
authenticating each user and dispatching the request appropriately. The Servlet and worker beans now
contain Java code that is owned by an individual in the software development role, and the syntax and
semantics of which may be modified without any changes to our JSP. The property sheets remain a
simple contract between the web-production team and the software developers.

The benefit of a dispatcher approach is in the control the Servlet has on the request. Since the Servlet
acts as the mediator, there is central forwarding control. As discussed, this also creates a nice role
separation between the lower level coding in the Servlet and the JSP coding. A drawback of this
architecture is that it involves more design work and more coding, since individual beans are created
instead of code fragments. A very simple project might be overly burdened by this extra overhead,
while more sophisticated efforts will benefit from the cleaner design.

Additionally, encapsulating as much Java code as possible into our Servlet and beans, and removing it
from the JSP source, will also have the added benefit of encouraging more elegant and refined Java
coding, because excessive Java code embedded within JSP source can quickly start to look like just
another scripting language, and the cut-and-paste mentality tends to take over. Moreover, a software
developer will be more inclined to refine code that they own, without potential dependencies and
conflicts with a web-production person. Of course the irony is that such unwieldy pages that are filled
with Java code are in more need than any of refactoring.

Updating our example to include improvements based on these very forces, we add to our worker bean
a factory that vends multiple storage implementations based on a parameterized factory method. Our
actual storage process may be modified easily and dynamically, simply by providing an implementation
that adheres to the Store interface. We move our basic file storage code into an implementation called
SimpleStore that implements the Store interface and is created by StoreFactory. We don't
actually include data access code in this example, but it would reside in a worker bean and would
reference the business delegate, which could then reference an EJB component. The Store interface
also hides implementation details, in this case those of the storage mechanism behind it, exposing a
well-defined interface instead.

The initial delegation point in this architecture is a JSP – we will see later another architecture in which
the initial point of delegation is a worker bean (Service-to-Workers). The subtle difference between the
two is worth discussing. In situations where there is on-going workflow that is necessary for the
generation of the data model, requiring multiple business calls, one needs to decide where to
encapsulate these business calls:

334
JSP Architecture

❑ In one case, the JSP may contain the business calls that are required to obtain the necessary
state for the intermediate model, which will be stored in the associated worker bean(s). The
JSP is not only responsible for the presentation of the data, but additionally has some
responsibility for coordinating the business calls, and may interact with different beans in
order to present multiple views of the same underlying models.

❑ On the other hand, if the Servlet delegates initially to a worker bean, then the Servlet will
need to adopt the responsibility for controlling these business calls, utilizing the worker
beans to make its requests. If the required data can be gathered with a single business call,
then dispatching this call to the worker bean directly from the Servlet allows the bean to
populate the entire intermediate model. The Servlet is then able to forward the request to
the JSP for presentation.

As you may have noticed, in the former scenario the JSP's responsibilities are increased as it fulfills part
of the role of the controller in addition to the view. One needs to decide what is right for the job and
move code forward or back based on the workflow and presentation needs. One issue to consider is that
adding business calls to a JSP page allows for reuse of this code conditionally across requests simply by
nesting pages, as in Mediator-Composite View, which we will discuss shortly. Adding business
invocations to the Servlet means either that these calls will be invoked for each request the Servlet
handles, limiting its potential for reuse, or that the Servlet may become cluttered with conditional logic
dictating which code to execute for a particular request.

The elements of the current "Mediator-View" example are:

❑ The HTML UI, which POSTs the request to the Servlet:


<jswdk-root>/examples/jsp/mediatorview/babygame2.html
❑ The Servlet, which dispatches to the JSP:
<jswdk-root>/examples/WEB-INF/servlets/BabyGameServlet.java
(source) and
<jswdk-root>/examples/WEB-INF/servlets/BabyGameServlet.class
(bytecode)
❑ The JSP:
<jswdk-root>/examples/jsp/mediatorview/BabyGame2.jsp
❑ The worker bean:
examples.mediatorview.BabyGameWorker2.java
❑ The supporting source code:
examples.mediatorview.StoreFactory, examples.mediatorview.Store,
examples.mediatorview.SimpleStore, examples.mediatorview.StoreException,
examples.auth.AuthenticatoFactory, examples.auth.Authenticator,
examples.auth.SimpleAuthenticator, examples.auth.AuthContext, and
examples.auth.SimpleAuthContext.

This supporting code must be included in the CLASSPATH that is used by the JSP engine.

The RequestDispatcher API


These architectures rely on a Servlet's dispatching a request to another resource. Prior to the Servlet
API 2.1, dispatching of requests to another dynamic resource was cumbersome, and limited because it
was not directly supported in the specification.

335
Chapter 12

The Servlet API 2.1 introduces the RequestDispatcher. Accessible via the ServletContext, the
RequestDispatcher implementation can dispatch a request to either a static resource, such as an
HTML page, or another dynamic resource, such as a Servlet or JSP. A request can be either 'forwarded'
or 'included', and state can be made available to the dispatched resource.

The include() method allows the programmatic equivalent of Server-Side Includes (SSI), while the
forward() method transfers control to the designated dynamic resource. A Servlet that invokes
RequestDispatcher.include() retains overall responsibility for the service request, handling the
response to the client. In this case, the Servlet has the opportunity to do any sort of clean up after all the
nested invocations have completed.

Once the Servlet dispatches to another dynamic resource with an invocation to


RequestDispatcher.forward(), though, the Servlet has completed its work. An example of the
latter type of forward dispatch is occurs in both the Mediator-View and Mediator-Composite View
architectures.

The method signatures that a Servlet may use to dispatch a request to another resource, are:

public void forward(ServletRequest request, ServletResponse response)


throws ServletException, java.io.IOException

public void include(ServletRequest request, ServletResponse response)


throws ServletException, java.io.IOException

Here is an example from within a Servlet:

RequestDispatcher dispatcher =
getServletContext().getRequestDispatcher("process.jsp");
request.setAttribute("user", user);
dispatcher.forward(request, response);

For a detailed description of the Servlet API, see Appendix C.

Mediator-Composite View
Sometimes we are building systems with dynamic template text as well as dynamic content. In other
words, there is content being generated dynamically, and the template text that surrounds this data is
also being constantly changed. Imagine that there are headers and footers in a page that are modified
quite often, notifying individuals of status changes or information of special interest. It may not be
desirable to recompile our JSP source each time this template text changes, since this involves a run
time delay and resource load. If we simply type our header and footer text directly into our JSP source,
then we will need to modify that source each time we want to change the template text, and our
modified source will need to be re-translated in order to service another request, causing this run time
latency, and this scenario will repeat itself each and every time the text undergoes even slight
modification.

Moving the header and footer template text to external files provides us with a solution to this
dependency on run time re-translation when our template changes. We move a portion of the template
text from our JSP source to another file, replacing it with the JSP include action:

<jsp:include page="header.html" flush="true" />

336
JSP Architecture

Unlike its counterpart the include directive (signified with <%@), which includes text at translation
time, the JSP include action substitutes the designated page into the JSP source at run time. Not only
have we made our solution more modular, we have provided a way to change template text on the fly
without the need for recompiling our JSP source. Of course, there is a run time cost for this processing,
but it is far less expensive than a full source compile. Such flexibility is useful, especially since the JSP
specification does not include much coverage of pre-compilation.

Not only can we dynamically include resources, such as static HTML template fragments within our JSP
source, but we can also include other JSPs, creating a multiple-level nesting of pages. In this case, the
presentation is built from numerous static and dynamic resources, which together make up the page
presented to the user. Each of these resources is potentially composed of additional nested pages.
Although the HTML template text is considered a static resource, meaning it is not generated
dynamically at run time, these template fragments are potentially a dynamic piece of the interface, since
each can be modified continually with immediate updates occurring in the containing presentation. This
'Mediator-Composite View' architecture is shown visually below:

Request

Servlet

gameheader.html
BabyGame2.jsp
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
header -.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
body
Response
footer gamefooter.html
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.

nestedheader.html
compositeinclude.jsp
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
header -.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
body

footer nestedfooter.html
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.
-.-.-.-.-.-.-.-.-.-.-.-.-.-.

worker bean business


delegate

Enterprise back-end
Java
Beans resource

Each of these architectures builds on the previous ones in some way, and in this case we have modified
the middle of the 'Mediator-View', while inheriting the front and back. As with the other dispatcher
architectures, the Servlet mediator dispatches to a JSP, which imports the aforementioned static and
dynamic resources. The figure above shows this nested server page including dynamic content
generated via an invocation on a helper bean, which gets to the business processing through a delegate
which once again acts as a façade to the back- end resource that may be "wrapped" in an Enterprise
JavaBeans component.

337
Chapter 12

As we have seen, the role of the delegate as a client-side business abstraction layer is to make business
calls on the actual back-end resource, such as remote invocations on an Enterprise JavaBeans
component. Once again, the role of the worker bean is to service the JSP page, preparing data for use
and dynamic presentation by the page. The worker bean serves as an intermediate model for the JSP
with which it is paired. Again, we are creating a more flexible architecture by abstracting out the worker
bean and the business delegate, so that the model for the JSP is not actually responsible for remote
invocations on business resources, and these two distinct parts of the system are more loosely coupled.

This architecture allows us to abstract out portions of our page, creating atomic pieces that can be
plugged into a composite whole in different configurations. For example, a checkout page on a shopping
site might present a user with the contents of a shopping cart. It is easy to imagine the shopping cart
component as an atomic portion of the presentation that might be included by other pages, as well, such
as a page that allows a user to survey, modify, or remove their current selections while still in
"shopping" mode, as shown in the next two figures:

Checkout
Please make any necessary modifications to your shopping cart.

Dan Malks - - Shopping Cart

Atomic presentation component Quantity Price Discount Remove

The Catcher in the Rye, J.D.Salinger 1 7.95 10%

The Sneetches, Dr. Seuss 1 10.95 10%

Some Boring Book, A. Guy 1 29.95 0% ü


Totals: 3 48.85

If you like Dr Seuss... try Mother Goose!!! Click Here to have a look!

Continue
Reset
Shopping

Checkout
Please make any necessary modifications to your shopping cart.

Click the 'Submit' button in order to proceed to our secure credit card processing page.

Dan Malks - - Shopping Cart

Atomic presentation component Quantity Price Discount Remove

The Catcher in the Rye, J.D.Salinger 1 7.95 10%

The Sneetches, Dr. Seuss 1 10.95 10%

Totals: 2 18.90

Submit Reset

338
JSP Architecture

A presentation component that is nested within another page will often represent a fairly coarse-grained
entity, such as the complete line-by-line inventory of the items in the aforementioned shopping cart, but
may be decorated with different header and footer information based on the context of its usage within
a page.

As an example, we will factor out the body of the presentation in our ongoing "Baby Game" example,
and decorate it with some headers and footers. So how has our code changed to support this
architecture?

Our HTML simply requires a change to the hidden input field dispatchto. Again, this value is used to
dispatch to the appropriate JSP and is used simply to allow for easy modification of these examples. In
this case we modify the value attribute to reference the JSP for our 'Mediator-Composite View'
example. The modified line now looks like this:

<input type="hidden" name="dispatchto"


value="/jsp/mediatorcompositeview/BabyGame2.jsp">

This modified user interface is now in


<jswdk-root>/examples/jsp/mediatorcompositeview/babygame2.html

Also, we have created some files containing the static header and footer template text to be included at
runtime into our composite display. Here's an example of what one of these header files looks like:

<center>
<H3><B>Baby Game 2000! Fun for the whole family!</B></H3><BR>
<hr>
</center>

<br>
<br>

This file includes the header template for the presentation that results from our "Mediator-Composite
View" example, as shown in the following screen shot:

339
Chapter 12

The elements of the current example are then:

❑ The HTML UI, which POSTs the request to the Servlet:


<jswdk-root>/examples/jsp/mediatorcompositeview/babygame2.html
❑ The Servlet, which dispatches to the JSP:
<jswdk-root>/examples/WEB-INF/servlets/BabyGameServlet.java
❑ The outermost JSP:
<jswdk-root>/examples/jsp/mediatorcompositeview/BabyGame2.jsp
❑ The composite JSP, included within the outermost JSP:
<jswdk-root>/examples/jsp/mediatorcompositeview/compositeinclude.jsp
❑ The worker bean:
examples.mediatorview.BabyGameWorker2
❑ The supporting code, which is reused unchanged from the previous example:
examples.mediatorview.StoreFactory, examples.mediatorview.Store,
examples.mediatorview.SimpleStore, examples.mediatorview.StoreException,
examples.auth.AuthenticatorFactory, examples.auth.Authenticator,
examples.auth.SimpleAuthenticator, examples.auth.AuthContext, and
examples.auth.SimpleAuthContext
This supporting code must be included in the CLASSPATH that is used by the JSP engine.
❑ The static template text, which is included dynamically at runtime to create the composite
display:
<jswdk-root>/examples/jsp/mediatorcompositeview/gameheader.html,
<jswdk-root>/examples/jsp/mediatorcompositeview/gamefooter.html,
<jswdk-root>/examples/jsp/mediatorcompositeview/nestedheader.html,
<jswdk-root>/examples/jsp/mediatorcompositeview/nestedfooter.html.

Service to Workers
The initial delegation point of the Service to Workers architecture, shown visually below, is a worker
bean that processes our business and data access code, once again via a client-side business abstraction.
As with each of the dispatcher architectures, the Servlet handles the request from the client, providing
the opportunity for the processing of common services. After the worker bean has completed its
responsibility of populating the intermediate model for the JSP, the Servlet dispatches to the JSP to
generate the presentation:

Request

Service

Servlet
Biz
Delegate

Resources
Workers
Response JSP
EJB
Java
Bean

340
JSP Architecture

This architecture provides a cleaner separation between the view and the controller, since the JSP page
is no longer making business calls, but simply accessing the state of the pre-populated worker bean.
Depending on the workflow needs of the system, a decision will have to be made about the suitability of
this architecture versus one where the initial delegation point is a JSP, such as the Mediator-View. The
cleaner separation of view and controller is indeed an important factor in the decision as well, and often
an overriding one. Certainly, if there is not a need for multiple business calls to generate the
intermediate model, then this type of architecture is a good choice.

In some cases, though, we may only want portions of a model to be utilized in a display and we may not
want to reuse this code across requests. If the granularity of the data access components necessitate
multiple calls to retrieve the data, then the Mediator-View architecture may be better suited to handle
this type of situation, since the server page will make business calls on the beans as necessary.

Our example will allow an authenticated user to examine his or her previously stored guesses. One
could imagine this feature being expanded to allow modification of the previously stored data, as well.

The HTML for the user interface consists of a couple input fields for the user to enter their id and
password for authentication purposes. The dispatchto hidden field has been modified appropriately,
and another hidden field, a flag called delegatetobean, has been added, and signals to the Servlet
that we want to use our worker bean as the initial dispatch point in this scenario. It allows us to reuse
the Servlet that we have been utilizing throughout our discussion with minor modifications. The screen
shot below shows this HTML page:

The HTML source for this page, <jswdk-


root>/examples/jsp/servicetoworkers/babygameSW.html, is as follows:

<!-- babygameSW.html -->


<html>
<head>
<title>Baby Game -- Retrieve stored guesses</title>
</head>
<body bgcolor="#FFFFFF">
<form method="post" action="/examples/servlet/BabyGameServlet" name="">
<center>
<h3>
Baby Game -- Retrieve stored guesses</h3></center>

<center>
<hr>
<br>

341
Chapter 12

Please enter your userID:<input type="text" name="guesser"><br><br>Please enter


your Password:<input type="password" name="password">
<br><br>
<input type=hidden name="dispatchto" value="/jsp/servicetoworkers/BabyGameSW.jsp">
<input type=hidden name="delegatetobean" value="true">

<input type=submit value="Retrieve">

</form>
</body>
</html>

The Servlet has been modified to include a conditional check for the delegatetobean flag. If it is set,
then the Servlet uses the worker bean as the initial delegation point. In previous examples, the Servlet
uses the JSP as the initial delegation point.

Adding this conditional, which will evaluate to true in this Service to Workers example only, allows us
to reuse similar Servlet code throughout our discussion; the Servlet source is shown below. After
successfully authenticating the user, the Servlet delegates to the worker bean (BabyGameWorkerSW),
instructing it to load previously stored guesses based on the user's id. The worker bean is set as an
attribute of the request object with the same bean id that is used in the presentation JSP (an id value of
"SWworker"). This allows the JSP to share this previously instantiated and initialized bean, instead of
creating a new one. In effect, we have passed the bean as an argument to the JSP.

The code for the Servlet is as follows, and is kept in <jswdk-root>/examples/WEB-


INF/servlets/BabyGameServlet.java:

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;

import examples.auth.*;
import examples.servicetoworker.BabyGameWorkerSW;

public class BabyGameServlet extends HttpServlet {


public void doGet(HttpServletRequest request,
HttpServletResponse response) {
processRequest(request, response);
}

public void doPost(HttpServletRequest request,


HttpServletResponse response) {
processRequest(request, response);
}

protected void processRequest(HttpServletRequest request,


HttpServletResponse response) {
try {
String guesser = request.getParameter("guesser");
String password = request.getParameter("password");

// Authenticate each request

342
JSP Architecture

Authenticator auth =
AuthenticatorFactory.create(AuthenticatorFactory.SIMPLE);
AuthContext authContext =
AuthenticatorFactory
.createContext(AuthenticatorFactory.SIMPLE);
authContext.addValue("guesser", guesser);
authContext.addValue("password", password);

auth.init(authContext);

if (auth.authenticate()) {
String dispatchto = request.getParameter("dispatchto");
String delegateToBean =
request.getParameter("delegatetobean");

// Delegate to worker bean


if (delegateToBean != null) {
BabyGameWorkerSW worker = new BabyGameWorkerSW();
worker.load(guesser);
request.setAttribute("SWworker", worker);
}

// In order to reuse this Servlet for multiple examples, we pass


// as a request parameter the resource name to which we dispatch
// our request
getServletConfig().getServletContext()
.getRequestDispatcher(dispatchto)
.forward(request, response);
} else {
PrintWriter outy = response.getWriter();
outy.println("Unable to authenticate, please try again.");
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}

In our earlier examples, we collected and stored a user's guesses to a text file. Now the example evolves
such that the worker bean called examples.servicetoworker.BabyGameWorkerSW adds a method
that loads our previously stored guesses from the store, based on an authenticated user's id. The method
is defined as follows:

public void load(String id) {


try {
Store storer = StoreFactory.createStore(StoreFactory.SIMPLE);
Properties props = (Properties) storer.load(id);
setProperties(props);
} catch (StoreException e) {
e.printStackTrace();
}
}

343
Chapter 12

Additionally, the worker bean has a method that is included so that our example may make use of JSP
error processing. The method is invoked as a guard clause from within the JSP in order to validate the
accuracy of the data before it is presented to the user. The method throws an exception if the bean's
state is incomplete, and is defined as follows:

public void validationGuard() throws Throwable {


if (getGender() == null) {
throw new Throwable("Error populating guess data.");
}
}

The JSP, <jswdk-root>/examples/jsp/servicetoworkers/BabyGameSW.jsp, is shown below.


Notice that it includes an explicit reference to an error page:

<HTML>
<HEAD><TITLE>Baby Game - Your Guesses</TITLE></HEAD>
<BODY bgcolor=FFFFFF>
<%@ page language="java" errorPage="errorPageSW.jsp" buffer="8k" %>

If an uncaught exception occurs within a JSP, the flow of control immediately transfers to the referenced
error page, in this case errorPageSW.jsp. As mentioned, the JSP includes a guard clause at the
beginning, which checks for valid data. If valid data does not exist, then the worker bean will throw an
exception, which will present the error page to the user, notifying him or her of the problem. In our
example, if the client enters an id and password for a valid user who has not previously stored any
guesses, then the bean state will be invalid and the bean's validationGuard() method will indeed
throw an exception. The error page display could easily be made as informative as necessary for the
user:

<jsp:useBean id="SWworker" class="examples.servicetoworker.BabyGameWorkerSW"


scope="request" />

Notice also that the JSP has the same bean id that the Servlet previously included in its
setAttribute() invocation. Thus, the JSP will reuse the existing bean, which was created in the
Servlet:

<jsp:setProperty name="SWworker" property="*" />

<% SWworker.validationGuard(); %>

<br>
<jsp:getProperty name="SWworker" property="guesser" />, here are your previously
stored choices:<br>
<table BORDER COLS=5 WIDTH="75%" >
<caption></caption>
<tr>
<td> <jsp:getProperty name="SWworker" property="gender" />
</td>
<td>
<jsp:getProperty name="SWworker" property="pounds" /> lbs <jsp:getProperty
name="SWworker" property="ounces" /> oz
</td>
<td>

344
JSP Architecture

<jsp:getProperty name="SWworker" property="month" /> <jsp:getProperty


name="SWworker" property="day" />
</td>
<td>
<jsp:getProperty name="SWworker" property="length" /> inches
</td>
</tr>
</table>

<br>

</BODY>
</HTML>

The full elements of the "Service To Workers" example are:

❑ The HTML UI, which POSTs the request to the Servlet:


<jswdk-root>/examples/jsp/servicetoworkers/babygameSW.html
❑ The Servlet, which dispatches to the JSP:
<jswdk-root>/examples/WEB-INF/servlets/BabyGameServlet
❑ The JSP:
<jswdk-root>/examples/jsp/servicetoworkers/BabyGameSW.jsp
❑ The ErrorPage:
<jswdk-root>/examples/jsp/servicetoworkers/errorpageSW.jsp
❑ The worker bean: examples.servicetoworker.BabyGameWorkerSW
❑ The supporting code, which is reused from a previous example:
examples.mediatorview.StoreFactory, examples.mediatorview.Store,
examples.mediatorview.SimpleStore, examples.mediatorview.StoreException,
examples.auth.AuthenticatorFactory, examples.auth.Authenticator,
examples.auth.SimpleAuthenticator, examples.auth.AuthContext, and
examples.auth.SimpleAuthContext

Servlets versus JSPs


JSPs can be used for most purposes, but there are some scenarios where Servlets are more appropriate.
As well as components such as the "mediator" Servlets used earlier in this chapter, Servlets are well
suited for handling binary data dynamically (for example, uploading files or creating dynamic images),
since they need not contain any display logic.

Consider the following: a JSP needs to display a banner image based on who is referring the user to the
site. This can be done by using the IMG tag like this:

<%@ page import="com.ibm.jspredbook.*;" errorPage="error.jsp" %>


<body bgcolor="#FFFFFF">
<!--the referer header is used to trap the url the user is coming from -->
<IMG SRC="/servlets/ImgServlet?from=<%=request.getHeader("Referer")%>">
</body>
</html>

345
Chapter 12

The Servlet referenced in the IMG tag, ImgServlet, is coded as:

package com.ibm.projsp;

import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.io.*;

public class ImageServlet extends HttpServlet {


private String docHome = ".";

public void service(HttpServletRequest request,


HttpServletResponse response)
throws ServletException, IOException {

HttpSession session = request.getSession(true);


ServletConfig config = getServletConfig();
ServletContext application = config.getServletContext();
File file = findFile(request, response);
if (file == null) {
return;
} else {
response.setContentType(application.getMimeType(file.getName()));
response.setContentLength((int) file.length());
sendFile(file, response);
}

protected File findFile(HttpServletRequest request,


HttpServletResponse response) throws IOException {

// We should store a flow-to-image mapping and return the appropriate


// File, without any platform-specific paths. Right now we will just
// return a GIF file.
File file = new File("c://weblogic//images/myimage.gif");
return file;
}

protected void sendFile(File file, HttpServletResponse response)


throws IOException {
int c = 0;
FileInputStream fileinputstream = null;
try {
ServletOutputStream servletoutputstream =
response.getOutputStream();
fileinputstream = new FileInputStream(file);

while ((c = fileinputstream.read()) != -1) {


servletoutputstream.write(c);
}

346
JSP Architecture

servletoutputstream.flush();
}
finally {
if (fileinputstream != null) {
fileinputstream.close();
}
}
}

This image can be cached in memory and updated every minute or so as needed. Keeping the data in
memory and using a servlet can save time and improve performance by not requiring access to the file
system every time a request is made.

Summary
We have examined how we architect systems using JSPs, Servlets, and JavaBeans, discussed benefits and
limitations of various approaches and actually seen an example that evolves to satisfy the constraints of
the various architectures.

We discussed a variety of architectural patterns, each of which we categorized as either a Page-Centric


or Dispatcher type of architecture. Page-Centric architectures have a JSP handling the request directly,
while Dispatcher architectures include a Servlet that handles the request and delegates to a JSP.

The architectural patterns we examined are:

❑ Page-View (Page-Centric)
❑ Page-View with Bean (Page-Centric)
❑ Mediator-View (Dispatcher)
❑ Mediator-Composite View (Dispatcher)
❑ Service-to-Workers (Dispatcher)

As we continue to investigate new ways to build our systems, we will continue to realize new
architectural patterns. Additionally, the specifications for these technologies continue to be refined and
improved in ways that will potentially demand modifications to current architectural patterns and the
realization of additional ones. The ability (in the post-1.0 JSP specifications) to factor code and
implementation details into a Custom Tag that might be used in place of a JavaBean is simply one
example. The integration of these technologies more closely with XML and XSLT is another.

This is certainly an exciting and important area of technology that continues to change at a rapid pace.
Hopefully, this information will help you better understand the current state of affairs with respect to
JSP architectures, and thus feel better positioned to follow the evolution of these architectural issues in
the future.

347
Chapter 12

348

You might also like