Contents | Prev | Next



A Template 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 of an application. 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.

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


JSP Page

The entry page of the example, main.jsp, is shown below. The first part of the page uses a set of nested tags-definition, screen, and parameter-to define a table of screen definitions for an application and select a specific definition based on the request attribute selectedScreen.

<%@ taglib uri="/tlt" prefix="tlt" %>
<tlt:definition name="tutorial" 
   screen="<%= (String)request.
      getAttribute(\"selectedScreen\") %>">
   <tlt:screen id="/home">
      <tlt:parameter parameter="title" value="Home Page" 
         direct="true"/>
      <tlt:parameter parameter="banner" value="/banner.jsp" 
         direct="false"/>
      <tlt:parameter parameter="body" value="/home.jsp"
         direct="false"/>
   </tlt:screen>
   <tlt:screen id="/first">
      <tlt:parameter parameter="title" value="First Page" 
         direct="true"/>
      ...
   <tlt:screen id="/second">
      ...
</tlt:definition>
The second part of the page uses the insert tag to insert parameters from the 
selected definition into the application screen.
<html>
   <head>
      <title>
         <tlt:insert definition="tutorial"
            parameter="title"/>
      </title>
   </head>
   <body bgcolor="white">
      <tlt:insert definition="tutorial" parameter="banner"/>
      <tlt:insert definition="tutorial" parameter="body"/>
   </body>
</html>
The template is instantiated by the Dispatcher servlet. This servlet first gets requested screen and stores as an attribute of the request. This is necessary because when the request is forwarded to main.jsp, the request URL info no longer reflects the original request (/home/example/*.jsp), but instead reflects the path (/template/main.jsp) of the forwarded page. Finally the servlet dispatches the request to main.jsp:

public class Dispatcher extends HttpServlet {
   public void doGet(HttpServletRequest request, 
      HttpServletResponse response) throws ServletException {
      request.setAttribute("selectedScreen",
         request.getPathInfo());
      try {
         getServletConfig().
         getServletContext().getRequestDispatcher(
         "/main.jsp").forward(request, response);
      } catch(Exception e) {
         e.printStackTrace();
      }
   }
}
The following figures show the home and first pages of the application:


Tag Handlers

The template tag library contains four tag handlers: DefinitionTag, ScreenTag, ParameterTag, and InsertTag. These tag handlers demonstrate the use of cooperating tags. DefinitionTag, ScreenTag, and ParameterTag comprise a set of nested tags handlers in which private objects are shared between parent and child tags. DefinitionTag creates a named object called definition that is used by InsertTag.

In doStartTag, DefinitionTag creates a private object that contains a hashtable of screen definitions. A screen definition consists of a screen identifier and a set of parameters associated with the screen. The table of screen definitions is filled in by ScreenTag and ParameterTag from text provided as attributes to these tags. Table 6 shows the contents of the screen definitions hashtable for the JSP page discussed in the previous section.

Table 6 Screen Definitions

Screen ID

Title

Banner

Body

/home

Home Page

/banner.jsp

/home.jsp

/first

First Page

/banner.jsp

/first.jsp

/second

Second Page

/banner.jsp

/second.jsp

In doEndTag, DefinitionTag creates a public object of class Definition, selects a screen definition based on the URL passed in the request, and uses the definition to initialize the Definition. If the URL passed in the request is /home, the Definition contains the items from the first row of Table 6:

Title

Banner

Body

Home Page

/banner.jsp

/home.jsp

public int doStartTag() {
   Hashtable screens = null;
   try {
   // look for the screens object or create if it does not exist
      screens = (Hashtable) getValue("screens");
      if (screens == null)
         setValue("screens", new Hashtable());
      else
         ...
   } catch (Exception e) {
      ...
   }
   return EVAL_BODY_INCLUDE;
}

public int doEndTag()throws JspTagException {
   try {
      Definition definition = new Definition();
      Hashtable screens = null;
      ArrayList params = null;
      TagSupport screen = null;
      if (getValue("screens") != null)
         screens = (Hashtable) getValue("screens");
      if (screens != null)
         params = (ArrayList) screens.get(screenId);
      else
         ...
      if (params == null)
         ...
      Iterator ir = null;
      if (params != null)
         ir = params.iterator();
      while ((ir != null) && ir.hasNext())
         definition.setParam((Parameter) ir.next());
         // put the definition in the page context
      pageContext.setAttribute(
         definitionName, definition);
   } catch (Exception ex) {
      ex.printStackTrace();
   }
   return EVAL_PAGE;
}
InsertTag uses the Definition object to insert parameters of the screen definition into the response. First it retrieves the definition object from the page context. The isDirect parameter attribute determines whether the parameter value is directly inserted into the response or treated as the name of a JSP file which is dynamically included into the response.

The definition for the URL /home is shown below. The definition specifies that the value of the Title parameter should be inserted directly into the output stream, but the values of Banner and Body should be dynamically included.

Parameter Name

title

banner

body

Parameter Value

Home Page

/banner.jsp

/home.jsp

IsDirect

true

false

false

public int doStartTag() {
   // get the definition from the page context
   try {
      definition = (Definition) pageContext.
         getAttribute(definitionName);
   } catch (NullPointerException e) {
      ...
   }
   // get the parameter
   if (parameterName != null && definition != null)
      parameter = (Parameter)definition.
         getParam(parameterName);
   if (parameter != null)
      directInclude = parameter.isDirect();
   return SKIP_BODY;
}

public int doEndTag()throws JspTagException {
   // flush data
   try {
      pageContext.getOut().flush();
   } catch (Exception e) {
      ...
   }
   try {
      // if parameter is direct, print to out
      if (directInclude && parameter != null)
         pageContext.getOut().print(parameter.getValue());
      // if parameter is indirect, 
      // include results of dispatching to page
      else {
         if ((parameter != null) && 
            (parameter.getValue() != null))
            pageContext.getRequest().
            getRequestDispatcher(
               parameter.getValue()).include(
               pageContext.getRequest(), 
               pageContext.getResponse());
      }
   } catch (Exception ex) {
      ex.printStackTrace();
   }
   return EVAL_PAGE;
}

Web Application Deployment Descriptor

The Dispatcher servlet is used to forward requests to the application template. The servlet-mapping element in the Web application deployment descriptor maps all URL patterns of the form /example/* to the dispatcher servlet. The servlet element then maps the dispatcher servlet to an instance of the Dispatcher class. The taglib element maps the logical name /tlt to the absolute location of the tag library descriptor. This allows a page author to use the logical name in the taglib page directive.

<servlet>
<servlet-mapping>
   <servlet-name>dispatcher</servlet-name>
   <url-pattern>/example/*</url-pattern>
</servlet-mapping>
   <servlet-name>dispatcher</servlet-name>
   <servlet-class>Dispatcher</servlet-class>
</servlet>
<taglib>
   <taglib-uri>/tlt</taglib-uri> 
   <taglib-location>/WEB-INF/taglib.tld</taglib-location> 
</taglib>


Contents | Prev | Next
Copyright © 2000 Sun Microsystems, Inc. All rights reserved.