Looking for Java resources? Check out the Java
Coffee Break directory!
Professional JSP Excerpt
Part One : Code Factoring and Role Separation / Architectures
This chapter examines a variety of ways to architect a system with JavaServer Pages, Servlets, and
JavaBeans. You 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.
When Sun introduced Java Server Pages, 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?
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.
This chapter examines a variety of ways to architect a system with JavaServer Pages, Servlets, and JavaBeans. You will see a series of different architectures, each a development of the one before.
When Sun introduced JSPs, some were quick to claim that Servlets had been replaced as the
preferred request handling mechanism in web-enabled enterprise architectures. Although JSPs are a key component of the J2EE, we must investigate further to understand its relationship with
Understanding that JSP is built upon 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 role do they fulfill?
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.
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
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):
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
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.
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:
first method is referred to here as the page-centric
approach. This approach involves request invocations being made
directly to JSP page.
the second method, the dispatcher
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.