Back Contents Next



  
  FAQ
  Java Tutorial
  Questions by Topic
  Sample test
  Other Certification sites
  Certification Tips
  Exam Objectives
  Java jobs
  Java News
  About Java Prepare
   Books
  Certification Books
  SCEA Books
  Online Books
   Tutorial Topics
  Language Fundamentals
  Operator and Assignments
  Declaration and Access Control
  Classes in Java
  AWT
  Event classes
  Threads
  Layout Managers
  Collections
  Files
   Advertisements
cover
   Feedback
  Please let us know your feedback
 
StoreBusters Marketing
javaprepare.com
your tool for Java Certification
home | tutorial | questions | test 1

JSP Architecture

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.


 

 

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.


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.


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:

 

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):

 

q        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.


q        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:

 

q        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.

q        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.


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.

 

 

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)


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.

 

 

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:


 

<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>


 

<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");


 

   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>


 

<%= 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.

 

 

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:


 

<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>


 

<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.


 

 

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.


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.

 


Back Contents Next
©1999 Wrox Press Limited, US and UK.
home | tutorial | questions | test 1