|
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.
- 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.
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.
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.
Placing data access in beans
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
).
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.
Separating Business Logic
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. 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.
- 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.
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.
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.
Placing data access in beans
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
).
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.
Separating Business Logic
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.
|