CONTENTS | PREV | NEXT | INDEX J2EE BluePrints



10.3 The View

The view determines the presentation of the user interface of an application. In the sample application, the implementation of the view is contained completely in the Web tier. In the sample application, three kinds of components work together to implement the view: JSP pages, JSP custom tags, and JavaBeans components.

JSP pages are used for dynamic generation of HTML responses. Custom tags make it easier for JSP pages to use JavaBeans components when the underlying model is complex. Custom tags can also help encapsulate presentation logic and make it modular and more reusable.

JavaBeans components represent the contract between JSP pages and the model. JSP pages rely on these beans to read model data to be rendered to HTML, while elsewhere in the system, the model and controller coordinate to keep the JavaBeans components up to date.

This section describes the JSP pages and custom tags that implement the view. Because the classes that implement JavaBeans components are intimately tied to their corresponding model classes, the discussion of the implementation of JavaBeans components and model classes is deferred until after the discussion of the model.


10.3.1 Shopping Interaction Interface

The shopping scenario described in Section 10.1.1.1 and the server-side scenario in Section 10.2.1 provide a behavioral specification for the shopping interaction interface. This section translates this specification into the set of views that the customer sees when interacting with the pet store application.

10.3.1.1 Screens

The user interface for the shopping interaction consists of a set of screens. A screen is the total content delivered to the browser when the user requests an application URL. In other words, a screen is what customers see when they navigate to one of our application's URLs. A screen can be composed of several components each contributing a different part of its content.

The specification includes some notion of the kind of screens the application displays to the customer and the dialogs it carries on with them. Taking this process further, results in the specification of a complete set of screens, each with a unique name.The significance of the names will become clear later when the discussion turns to how the controller selects a view for each response. The following list identifies what model information it presents and what user gestures it can generate.

This completes the initial set of screens that are presented to the customer during the course of a shopping interaction with the application. As the application evolves, more screens may be added and existing screens modified.

10.3.1.2 Graphical Design

Since we already identified the major screens in the application and the data that needs to be shown as part of each screen, we can now involve graphic design and HTML specialists to create the layout, look, and feel of each of the screens.

There are two parts to this design: design of the custom content of each screen and design of a common template which remains consistent with each of the screens. The preceding scenarios have identified the data that needs to go into each of the screens as well as the dynamic portions of the template.

The artist needs an idea of the size and shape of each of the data element that needs to be shown in each of the screens. They can make good progress with the graphical design at this point using storyboarding techniques, even without an actual implementation of the rest of the application available to them. This is one major advantage of decoupling the design of the user interface from the rest of the application.

The contract with the graphic design artists is just how the application makes the model data required for each screen available to the screen. As we shall see later in this section, this is where the JavaServer Pages technology comes into play.


10.3.2 JSP Pages

The JSP pages provided by the pet store application use a generic template mechanism and application-specific JavaBeans components. This section describes the template mechanism and discusses several example JSP pages. The JavaBeans components are discussed in Section 10.5. General guidelines on how to use JSP technology can be found in Chapter 4.

10.3.2.1 A Template Mechanism

While sketching out the shopping interaction interface of the application, it is clear that there are elements that we want to be part of each screen. Some of these are:

Among the elements that change on each page are the body and the title. Other elements, such as keywords and meta-headers, may also change with each screen as well.

To add headers and footers to every JSP page, the designer could create header and footer JSP files and have each JSP page include these at appropriate places. Such a technique is illustrated in Code Example 10.1.


<%@ include file="header.jsp" %>
	...
	content of this screen
	...
<%@ include file="footer.jsp" %>
Code Example 10.1 Templating Using JSP Include Statements

However, this approach runs into several limitations if we try to make the template more elaborate, using HTML tables, side bar, and so on. The header and footer files would have to be constructed and formatted properly to make sure the body appears where intended. For instance, correct HTML requires opening HTML tags in the header and a closing HTML tag in the footer so that the body can be enclosed between them. This requires either hand-coded HTML or specialized authoring tools to ensure correct design and correct HTML. The problem becomes compounded if we want more than just one contiguous chunk of HTML to change on each screen. For instance, each screen might want to provide its own HTML title as well as custom content. These features require a more flexible screen layout mechanism.

A template mechanism provides a way to separate the common elements that are part of each screen from the elements that change with each screen. Putting all the common elements together into one file makes it easier to maintain and enforce a consistent look and feel in all the screens. It also makes development of individual screens easier since the designer can focus on portions of a screen that are specific to that screen while the template takes care of the rest.

This section reviews the design and implementation of the sample application's screen template mechanism. The concept of a presentation template can be applied to almost any Web application in one form or another. The sample application's template mechanism is designed so that you can easily adapt it to other applications.

The template itself is a JSP page, with place holders for the parts that need to change with each screen. Each of these place holders is referred to as a parameter of the template. For example, a simple template could include a title text parameter for the top of the generated screen and a body parameter to refer to a JSP page for the custom content of the screen.

Once you have a template, you can generate different presentation screens from it simply by passing it different parameters. This process is called instantiation of the template. A specific screen is completely characterized by identifying the template page, and the parameters to pass to the template. The set of parameters that completely defines a screen is called a screen definition.While a large application could use multiple templates; the pet store application uses a single template for all its screens. However, the mechanism it uses is designed to support multiple templates.

From the templating mechanism's point of view a screen is the instantiation of a template according to its screen definition. Figure 10.3 illustrates the relationship between a template, a screen definition, and the resulting presentation screen.

Figure 10.3 Defining a Screen in Terms of a Template and Its Parameters

Code Example 10.2 shows the contents of template.jsp, the template file used in the sample application.


<%@ page errorPage="errorpage.jsp" %>
<%@ page import="com.sun.estore.control.Web.ScreenNames" %>
<%@ taglib uri="WEB-INF/tlds/taglib.tld" prefix="j2ee" %>
<%@ include file="ScreenDefinitions.jsp" %>
<HTML >
	<head>
		<title>
			<j2ee:insert template="template" 
				parameter="HTML Title" />
		</title>
	</head>
	<body bgcolor="white">
		<j2ee:insert template="template" parameter="HTML Banner" />
		<j2ee:insert template="template" 
			parameter="HTML TopIndex" />
		<j2ee:insert template="template" parameter="HTML Body" />
	</body>
</HTML >
Code Example 10.2 template.jsp

The template is instantiated by forwarding to or dynamically including the template.jsp page. Forwarding is performed using the jsp:forward standard action or by calling the forward method of a RequestDispatcher; inclusion is performed using an include directive or standard action or by calling the include method of a RequestDispatcher.

An appropriate screen definition must be set up in the request scope before invoking template.jsp. JSP pages can access objects in request, session, and application scopes. Since a screen is presented in the context of a specific URL request from the user, the appropriate screen definition needs to be set in the request scope before the template file is invoked. The other possible JSP scopes, session and application, are broader--they're more appropriate for setting general site and user-specific portions of the template.

The following examples show how template.jsp works. It uses the j2ee:insert custom tag to identify place holders in the template. This tag is responsible for extracting the screen definition from the request scope and inserting it into the page. Code Example 10.3 contains the implementation of the insert tag.


public class InsertTag extends TagSupport {
	private boolean directInclude = false;
	private String parameter = null;
	private String templateName = null;
	private Template template = null;
	private TemplateParameter templateParam = null;

	public void setTemplate(String templateName){
		this.templateName = templateName;
	}

	public void setParameter(String parameter){
		this.parameter = parameter;
	}

	public int doStartTag() {
		try {
			if (templateName != null){
				template = (Template)pageContext.getRequest().
								getAttribute("template");
			}
		} catch (NullPointerException e){
			...
		}

		if (parameter != null && template != null) 
			templateParam = (TemplateParameter)template.
				getParam(parameter);
		if (templateParam != null) 
			directInclude = templateParam.isDirect();
		return SKIP_BODY;
	}

	public int doEndTag() throws JspTagException {
		try {
			pageContext.getOut().flush();
		} catch (Exception e){
			...
		}
		try {
			if (directInclude && templateParam != null) {
				pageContext.getOut().
					println(templateParam.getValue());
			} else if (templateParam != null)  {
				if (templateParam.getValue() != null) 
					pageContext.getRequest().
						getRequestDispatcher(templateParam.
							getValue()).include(pageContext.
								getRequest(), 
									pageContext.getResponse());
			} 
		} catch (Throwable ex) {
			...
		}
		return EVAL_PAGE;
	}
}
Code Example 10.3 Insert Tag Implementation

The insert tag gets values of the parameters passed to it. The parameters are automatically set by the JSP runtime environment and the tag focuses on inserting the appropriate parameters into the response. Parameters can be direct or indirect. Direct parameters are inserted as-is into the response stream. Indirect parameters are treated as the name of a JSP file, and that file is dynamically included into the response stream. This makes it possible to pass the title of a page as text using a direct parameter, and the body as the name of a JSP file to include using an indirect parameter.

10.3.2.2 View Selection

In a Web application, each screen presented to the user can be considered as a different view. However, unlike the classic MVC architecture, all these views share the same controller. There needs to be a mechanism that allows the controller to choose a particular view to render in response to a user request. In the sample application, the controller makes this selection by specifying the screen ID of the screen to present as the response. This screen ID is mapped to a screen definition, then the template is instantiated.

Recall that the file template.jsp defines the template for the sample application. This file includes another file, ScreenDefinitions.jsp, which defines all the screens of the sample application. When the controller invokes the template file at request time, it sets the appropriate screen definition in the request scope. The template file passes this information to the screen definitions file which then returns the appropriate screen definition for the request.

One goal in structuring template and screen definition files is to facilitate internationalization (discussed in Section 4.5). This is achieved by separating text content from Java code. Since screen definitions that contain direct and indirect parameters are candidates for internationalization, we want to keep ScreenDefinitions.jsp devoid of Java technology code. We achieve this through the use of JSP custom tags. Code Example 10.4 contains an excerpt from ScreenDefinitions.jsp, which uses Screen and Parameter custom tags to pass text and the contents of files to the response.


<%@ page import="com.sun.estore.control.Web.ScreenNames" %>
<jsp:useBean 
  id="screenManager" 
  class="com.sun.estore.control.Web.ScreenFlowManager" 
  scope="session"/>

<j2ee:CreateTemplate template="template" 
	screen="<%=screenManager.getCurrentScreen(request)%>">
	<j2ee:Screen screen="<%=ScreenNames.MAIN_SCREEN%>">
		<j2ee:Parameter parameter="HTML Title" 
			value="Welcome to Java Pet Store Demo" direct="true"/>
		<j2ee:Parameter parameter="HTML Banner" 
			value="/banner.jsp" direct="false"/>
		<j2ee:Parameter parameter="HTML Body" 
			value="/index.jsp" direct="false"/>
	</j2ee:Screen>
	<j2ee:Screen screen="<%=ScreenNames.SIGN_IN_SUCCESS_SCREEN%>">
		...
	</j2ee:Screen>
	...
</j2ee:CreateTemplate>
Code Example 10.4 ScreenDefinitions.jsp

When it is included at request time by the template file, ScreenDefinitions.jsp uses ScreenFlowManager, a component of the controller, to identify the view that the controller wishes to select. The nested custom tags arrange for that screen's definition to be set into the request scope when this file invoked.

In summary, the JSP pages template.jsp and ScreenDefinitions.jsp work together to create the page viewed by the user. Figure 10.4 depicts the process of view selection and instantiation in the sample application.

Figure 10.4 View Selection and Instantiation


10.3.3 Examples

For the most part, the sample application's presentation JSP pages use fairly straightforward JSP elements. This section examines three example presentation JSP pages: the home screen page (index.jsp), the products-by-category page (productcategory.jsp), and the shopping cart page (cart.jsp).

10.3.3.1 Home Screen

The home screen of the Java Pet Store Demo application is shown in Figure 10.5.

The JSP source used to generate the screen, contained in the file index.jsp, appears in Code Example 10.5. The screen is composed of the banner that appears in all the Java Pet Store Demo screens, a list of the product categories (sideindex.jsp) supported by the application, and an imagemap (splash.jsp) of the categories. The banner does not appear explicitly, because it is constructed by the template described in Section 10.3.2.1.

Figure 10.5 Home Screen


<table border="0"  cellspacing="0" width="600" >
  <tr>
    <td> 
      <%@ include file="sideindex.jsp"%> 
    </td>
    <td bgcolor="white" height="300">
      <%@ include file="splash.jsp" %>
    </td>
  </tr>
</table>
</HTML >
Code Example 10.5 index.jsp
10.3.3.2 Product Category Screen

The screen that lists all the products in a category is shown in Figure 10.6.

The JSP source used to generate the screen, contained in the file productcategory.jsp, appears in Code Example 10.6. In this code sample, the first statement sets the catalog variable to point to an instance of the JavaBeans component CatalogWebImpl. This component is used to retrieve the catalog entries for a particular product category. The category is retrieved from the implicit request object with the getParameter("category_id") method. Once the category and its products are retrieved, JSP scriptlets are used to generate the table of products.

Figure 10.6 Product Category Screen


<jsp:useBean 
  id="catalog" 
  type="com.sun.estore.catalog.model.CatalogModel" 
  class="com.sun.estore.catalog.web.CatalogWebImpl" 
  scope="application"/>

<%
String key = request.getParameter("category_id");
Category category = null;
if (key != null)  category = catalog.getCategory(key);
if (category != null) {
	Collection products = null;
	products = catalog.getProducts(key, 0, 20);
%>
<p>
<font size="5" color="green"><%= category.getDescription()%></font>
<p>

<table border="0" bgcolor="#336666">
<tr background="../images/bkg-topbar.gif">
	<th><font color="white" size="3">Category ID</font></th>
	<th><font color="white" size="3">Category Name</font></th>
</tr>

<%
	Iterator it = null;
	if (products != null) it =products.iterator();
	while (it.hasNext()) {
		Product product = (Product)it.next();
%>
	<tr bgcolor="#eeebcc">
	<td><%= product.getId() %></td>
	<td>
		<a href="product?product_id=<%= product.getId() %>">
	    <%= product.getName()%></a>
	</td>
	</tr>

<% } %>
</table>
<%
	} else {
   // Category was not found:
%>
<p>
<font size="5" color="red">Unable to Locate Category ID <%= key 
%></font>

<% } %>
Code Example 10.6 productcategory.jsp
10.3.3.3 Shopping Cart Screen

The screen that displays the contents of a user's shopping cart is shown in Figure 10.7.

The JSP source used to generate the screen, contained in the file cart.jsp, appears in Code Example 10.7 and Code Example 10.8. In this code sample, the first statement sets the cart variable to point to an instance of the JavaBeans component ShoppingCartWebImpl. This component is used by the shopping cart table. The include statement towards the middle of the code sample (begins with "<%@ include") causes the page to include the shopping cart table (illustrated in Code Example 10.8). The page also contains a button that accepts a modification to the shopping cart, and a link to a checkout page.

Figure 10.7 Shopping Cart Screen


<jsp:useBean 
	id="cart" 
	class="com.sun.estore.cart.Web.ShoppingCartWebImpl" 
	scope="session">
<% 
	cart.init(session); 
%>
</jsp:useBean>
<p>
<% 
  if (cart.getSize() > 0) { 
%>

<font size="5" color="black">Shopping Cart:</font>
<p>
  <form action="cart">
  <input type="hidden" name="action" value="updateCart">
  <table bgcolor="white">
    <tr>
      <td> 
        <%@ include file="changeable_carttable.jsp" %>
      </td>
      <td>
        <input type="image" border="0" src="../images/cart-update.gif"
name="update">
      </td>
    </tr>
  </table>
  </form>
  <a href="checkout"><img src="../images/button_checkout.gif" 
alt="Proceed To Checkout" border="0"></a> 

<% 
  } else { 
  // The cart is empty
%>

  <font size="5" color="red">Shopping Cart is empty.</font>
<% } %>
Code Example 10.7 cart.jsp

Code Example 10.8 uses JSP scripting capabilities to display all the rows in the shopping cart. The page retrieves shopping cart items from the cart component set by the enclosing page cart.jsp. The page also includes a button that allows a user to delete an item from the shopping cart.


<table bgcolor="#336666">
	<tr background="../images/bkg-topbar.gif" border="0">
    <th><!-- for the remove column --></th>
	<th><font size="3" color="white">Item ID</font></th>
	<th><font size="3" color="white">Product Name</font></th>
	<th><font size="3" color="white">In Stock</font></th>
	<th><font size="3" color="white">Unit Price</font></th>
	<th><font size="3" color="white">Quantity</font></th>
	<th><font size="3" color="white">Total Cost</font></th>
	</tr>

<%--
% Loop through each item in the shopping cart.  The current item is
% available to the jsp block within the loop as "item"
--%>

<%
  Iterator it = cart.getItems();
  while ((it != null) && it.hasNext()) {
    CartItem item = (CartItem)it.next();
%>

<tr bgcolor="#eeebcc">
<td>
	<a href="cart?action=removeItem&itemId=<%=item.getItemId()%>"><img
src="../images/button_remove.gif" border="0" 
alt="Remove Item From Shopping Cart">
	</a>
</td>

<td><%= item.getItemId() %></td>
<td>
	<a href="productdetails?item_id=<%=item.getItemId()%>">
	<%=item.getAttribute()%> <%=item.getName()%>
	</a>
</td>

<td><%=(inventory.getInventory(item.getItemId()) 
	>= item.getQuantity()) ? "yes" : "Back Ordered"%></td>
<td><%=JSPUtil.formatCurrency(item.getUnitCost())%></td>
<td><input name="itemQuantity_<%=item.getItemId()%>" 
	type="text" 
	size="4" 
	value="<%=item.getQuantity()%>">
</td>
<td><%=JSPUtil.formatCurrency(item.getTotalCost())%></td>
</tr>

<% } // end for loop %>

<tr background="../images/bkg-topbar.gif">
    <td></td>
    <td><font size="3" color="white">Total:</font></td>
    <td></td>
    <td></td>
    <td></td>
    <td></td>
    <td><font size="3" color="white"> 
		<%=JSPUtil.formatCurrency(cart.getTotalCost())%
		</font></td>
</tr>
</table>
Code Example 10.8 changeable_carttable.jsp


CONTENTS | PREV | NEXT | INDEX
Copyright © 2001 Sun Microsystems, Inc. All Rights Reserved.