View Templates with JSP

Jorge Simão

Intro

Composing views with templates is a common approach to reduce web site development effort and provide a consistent look-and- feel through out the application. One or more templates may be used by a webapp views to specify how different shared and page-specific components are layout. Components may follows organizational, asthethic, and functional roles, such as: header, footer, global and local navigation menus, and main content. The layout of the template specifies how components are arranged relative to each other by setting their relative or absolute positions and/or size. The template also provides components taht are shared across pages. The main content of the page is different for every page.

The use o view templates works to ensure a shared page structure. This benifits the end-user for increased predictability, consistency of layout, and of navigation options. View templates also ensure common style elements, such as fonts, colors, background images, and many other attributes that are commonly set using stylesheets. From the developers perspective, template reduces development and maintainence effort. Each page gets only the information specific to its main content, with minimal or no decorations. Changing general look-and-feel of a web site is also much simpler. Only the template and its use needs to be changed. Old wisdom for modern web designers, some may say.

It may seam that implementing view templates with plain JSP techology is a particular hard thing to do, unless one uses an extra template framework such as SiteMesh or Apache Tiles. In this article, I will show that JSP already contains the basic mechanisms that can be used to implement pratical view template. This are the JSP include directive or include tag, and script expressions. The point to notice is that inclusion of resources should use resource expressions that evaluate to different values depending on the context, rather than the more common case where resource resolve to fixed locations.

View Layouts, Templates, and Themes

In the introduction we defined view templates as layouts structures. In practice, is useful to make the further distinction between abstract layouts and concrete templates. The abstract layout specifies the global arrangement of components filling funcional roles, such as header, footer, menus, and main content. A view template uses a particular layout, but also assigns some shared components to the functional roles. Thus, while a layout specifies where headers and footers are locate and how big they should be, it is actual template that select the specific header and footer for the webpages (e.g. to show the company or website name and logo, contact and copyright info, and so forth).

Layouts Structures

Design of layouts structures and view templates reflect a combination of issues such as the astheric preferences of the web designer, the expectations of the user community, and the presentation and navigation demands created by the content of the web site. Some layout structure are quite frequently used, as the offers a general or widely-applicable solution to website design. This is specially true for simple layouts with a single header, footer, and main content. Menus vary more in location and number across layouts. Figure above shows several simple layouts frequenctly used in real websites:

Examples of simple layout structures.

Templates

Menus may also be automatically provided by the template, possibly adapting style depending on the page using the template. Templates also define or include the style elements that are shared across pages.

Thus, a template may select the specific header and footer for the webpages (e.g. to show the company or website name and logo, contact and copyright info, and so forth). Menus may also be automatically provided by the template, possibly adapting style depending on the page using the template. Templates also define or include the style elements that are shared across pages.

Figure above summarizes the relationship between abstract layout, components, templates, and style:

A template combines an abstract layout with shared components and style.

Templates are used to statically create or dynamically render specific web pages to be delivered to client browsers. To created individual web pages the missing components of the template need to be provided. Naturally, the template must have at least one component placeholder and at least one such component should be provided to generate a page.

Figure above illustrates how a template is combined to specific pages components, such as main content and title, to produce an actual page to be rendered to the end-user.

An end-user page is created by combining page-specific components to the template.

The all purpose of templates is to be able to apply a template to multiple pages, to produce the end-user pages sharing common elements. In many cases a single template can be applied to all pages in a web site, however it is also possible to have different parts of a website to use different templates. Even if a single template can be applied to all pages in a web site, it may be desirable to have users costumize or select different themes to view the application. For example, some user might prefer to have navigation or content menus on the left side, while other user prefer menus on the right side.

Figure above below illustrates the process by which a single template is used to produce multiple end-user pages:

A single template can be used to generate multiple web pages.

Themes

Templates are also most useful to implement themes since different template or set of templates may be used to render different themes. New themes may introduce new or replace view components, or simply use a different layout structure with the same components. Additionally, templates for different themes may or may not share elements of style and stylesheets. Changing side location of navigation menus is an example where themes can be implemented by changing the layout structure of templates without replacing or adding componenet or stylesheets.

Figure above illustrates how different templates can be used to implement themes in a web site:

Two different templates are used to implement different themes for a web site.

Design-Patterns to Implement View Templates

To actually implement a templating system, components, layout, and templates, and components need to be represented in parent-child structures. Leaf nodes represent isolated components, and internal nodes represent the layouts and templates. A Template is the root of a tree, where child nodes represent the shared components and the placeholders used to tailor the template for each individual page. The process by which this tree is created is what distinguish the different approaches to templating systems.

Figure above illustrates how layout, components, templates, and placeholders are organized in a the tree structure.

Layout, components, templates, and placeholders are organized in a tree structure.

Composite Design-Pattern

In composite design-pattern approach pages are created by incrementally reducing the number of missing components, until the page is fully composed. A template is created by composing a layout with specific shared components that fit some functional roles in the layout. An end-user web page is created by composing the template with page specific components. In this approach the composition of the end-user page is made explicity. For each end-user page a composition page ise used specify the details of the composition. A consequence of this, is that if a web site has N pages, then we need on the order 2×N view resources (files) to create the site. This is N files for the main content, and additional N files for the composition pages. APACHE TILES is a popular templating framework that uses the composite design-pattern with JSP. JSF standart web development framework also as direct support for templating using the composite design-pattern.

Figure above illustrates how in the composite design-pattern builds end-uses pages by combining templates, with with page specific components..

In the composite design-pattern end-uses pages are created by composing the template with page-specific components.

Decorator Design-Pattern

In the decorator design-pattern page are created by augmenting or decorating page content with the template information. This is made automatic by the templating system, so that if a web site has N pages then we need only on the order of N view resources to create the site. SITEMESH is another popular templating framework that uses the decorator design-pattern with JSP.

Figure above illustrates how the decorator design-pattern has the templating engine automatically decorates main content page component with template layout and style.

In the decorator design-pattern the templating engine automatically decorates the main content page with the template.

Composite vs. Decorator Design-Pattern

The decorator design-pattern has the appeal that of not requiring explict composition of pages. The drawback is that the templating engine needs to setup so that pages request are intercepted to add the required decoration to pages. This is problematic if there are limitation to the programs that can be run on the web server. On the other hand, the composite design-pattern only needs some mechanism for composing components such as a file include, but is more verbose. This comparison assumes that page composition is done dinamically, at request time. If page composition is done statically (before deployment), that the decorator templating engine can operate outside the web server where limitation to running programs does not exist (e.g. in the web developer workstation). Thus, it can be argued that templating by static decoration provides the best trade-off solution to page composition.

Table above summarizes the differences between the composite and decorator design-patterns when applied to view templates.

Criteria / Design-pattern

Composite Decorator
Files/Page 2 1
Number files for N pages 2 ×N N
Max. page specific components/Page M 1
Modification cost for N pages N 1

Composite vs. decorator design-pattern for view templates.

Below, we show how the composite design-pattern can be used in JSP to implement view templates. Using or implementing the decorator design pattern requires an additional mechanisms such a request filters of the Servlet Technology. This is the mechanism use by the framework SiteMesh.

JSP Includes and Path Expressions

Java Server Pages (JSP) is the original view technology based on the Java infra-structure. It was motivated by hard and error-prone work involved in creating dynamic pages using the Servlet technology. JSP pages mix (X)HTML tags, library tags, text content, directives, and scripting elements such as expressions and code fragments (calles scriplets). It is the scripting that mostly allow dynamic parts of pages be generated at request time. On the other hand, if care is not taken, developing web sites with JSP is as laborious (or more) than writing sites with only static (X)HTML pages. One reason for this is that if no templating solution is used, many parts of the web pages need to be repeat by copy-paste across many web pages. Fortunale, JSP already as mechanisms that allow pages to include other pages as components parts, and this is turn allow template to be defined and assembled according to the composite design-pattern.

Include Directive and Include Tag

JSP supports two way to include a file as part of JSP page. This is the include directive <%@include%> and the include tag <jsp:include>. This include directive is used to include a fixed resouce, such as a text file. html file, or another JSP page. This works by inserting the textual content of included file in the place of JSP page where the include directive appears. The content of the included JSP page can contain dynamics elements such as scriplets, EL expressions, and tags from a tag lib. However, the content can not change at run-time. The syntax is as shown below:

<\%@ include file="..." \%>}

Attribute file specifies the relative or absolute location of a resource file. Absolute file paths are resolved in relation to the root directory of the deployed application.

The include tag <jsp:include> can also be used to include a content of another resource to a JSP page. The mechanism of inclusion is different though. The include tag works by creating an additonal request to the web container with the resource url specified in attribute page. The syntax is as follows:

<jsp:include page="..." />

Attribute page is the location of a view resource to be included in the body of the including JSP page. It can be a relative or absolute file name or a general URL, provided it resolves to resource in the same application.

Both mechanisms, include directive and include tag, can be use to reuse components as parts of JSP pages. An example is shown below using the include tag:

<html>
<head>
  <link href="mycom.css" type="text/css" rel="stylesheet" />
  <title>Welcome to MyCom</title>
</head>
<body>
  <jsp:include page="header.htm" />

  <table><tr>
  <td> <jsp:include page="menu.htm" /> </td>
  <td>
    <!--page specific content -->
	<h1>Welcome to MyCom</h1>
  </td>
  </tr></table>
  <jsp:include page="footer.htm" />
</body>
</html>

In the example above, several include directives are used to compose the page with common components parts: the header, the footer, and the side menu. Page specific markup appears below the XML comment. The page also contains the markup required to define the page layout and link to the CSS stylesheet. This markup should be the same across pages for consistency of layout.

A problem with the above approach for page composition, is that common markup needs be repeat (copy-paste) across all pages. This is very inconvinient, since makes pages creation and maintainance hard. There is also no way to enforce a common re-usable page structure troughout the application. Thus, the approach is very probe to editing errors that generate inconsistency of layout across pages. An additional inconvinience, is that layout and page main content are mixed in the same file. This obscures the main content of the page makes it harder to read and edit for the developer. It also violates the basic principle of (X)HTML which is the separation of content from presentation issues. Ideally, we would like to have one or more files that contain the layout and template information, and have files that contain only the page specific content.

Resource Expressions

An alternative approch is to use include directives or tag whose path attribute evaluates to different values depending on the context. This is done by using script expressions as path values. When using the JSP Expression Language (EL), the syntax for include tags is as follows:

<jsp:include page="${el-expr}" />

It is also possible to use a Java expression for the same purpose, which was the only available mechanism in JSP before the introduction of EL in version 2.0. The syntax is as follows:

<jsp:include page="<%= java-expr %>$ />

For the static include directive the syntax is ajusted accordingly:

<\%@ include file="${el-expr}" \%>}
<\%@ include file=<%= java-expr %> \%>}

In all cases, the resource expression should evaluates to a resource location. Additionally, the expression should depend on an externally set variable, such as a request parameter, request scoped attribute, or a JavaBean property. This makes the include directive to works as a component placeholder, whose specific value can be set from outside the page to fill-in missing components.

Templating with JSP

Here we put forward an approach to implement view templates with the composite design-pattern in JSP. Each include directive or tag is set with a resource expression to specify where variable page components should be inserted. This is used to define both abstract layout pages, and the more detailed templates. Templates include the layout page, and additionally set the context variables to include specific shared components. End-user pages also use includes to include the template and set context variables for the page main content and page title. We start by using request scoped variables to set up the resource inclusion context.

Context from Request Attribues

Below, we show a JSP file for a layout template using include directives with EL expressions in the page attribute.

<%-- Abstract Layout I: /WEB-INF/templates/classic1.jsp --%> 
<html>
<head>
  <link href="${requestScope.css}" type="text/css" rel="stylesheet" />
  <title> ${requestScope.title} </title>
</head>
<body>
  <jsp:include page="${requestScope.header}" />

  <table><tr>
  <td> <jsp:include page="${requestScope.menu}" /> </td>
  <td>
    <!--page specific content -->
  	<jsp:include page="${requestScope.body}" />  
 </td>
 </tr></table>
  <jsp:include page="${requestScope.footer}" />
</body>
</html>

The pre-defined JSP variable requestScope is used access request scoped variables. EL expressions are used to name and access the variables. We use six request scoped variables: four variables are used to reference layout components (header, footer, menu, and main body); one variable is used to get the title of the page; and the other variable is used to specify the stylesheet. Note that, in the informal discussion and figures shown earlier, we introduced the page title and stylesheet markup in the template. Here we introduce it earlier in the layout structure, without any serious consequences.

The value of request scoped attributes can also be get using Java Expression as follow:

<jsp:include page="<%= request.getAttribute("body") %>$ />

We will keep using EL expressions since they are less verbose.

Assuming the layout file is located in /WEB-INF/templates/classic1.jsp, then we can define a template as follows:

<%-- Template for MyCom Site: /WEB-INF/templates/mycom-template.jsp --%> 

<%-- Setup Context variable to point to component files:
	header, meny, footer, and stylesheet --%> 
<%
request.setAttribute("css", "mycom.css");
request.setAttribute("header", "header.jsp");
request.setAttribute("menu", "menu.jsp");
request.setAttribute("footer", "footer.jsp");
%>

<%-- Include abstract layout --%> 
<jsp:include page="classic1.jsp" />

To create the template we need to setup the context for the layout and then include the layout. The context for the layout is setup with a script fragment (scriptlet). It use the pre-defined request variable and method setAttribue to set the request scoped variables to point to the shared components of the template. The layout is included in a JSP include directive. Attribute page is set to point to the layout file classic1.jsp. Note that in the code above we assume that the layout and shared components are located in the same directory. If not, the directory should also be included in the file names.

The code examples above used the include tag, but the include directive can as well be used. The important difference is that with the include directive one should use absolute file path if the files for the main content of pages are stored in a different directory than the layout, template, and shared component files. This is because when using nested static includes the reference location for relative paths is the directoty of the top-level JSP page. The same template adapted to work with the static include directive is shown below:

<%-- Template for MyCom Site: /WEB-INF/templates/mycom-template-static.jsp --%> 

<%
request.setAttribute("css", "mycom2.css");
request.setAttribute("header", "/WEB-INF/templates/header.jsp");
request.setAttribute("menu", "/WEB-INF/templates/menu.jsp");
request.setAttribute("footer", "/WEB-INF/templates/footer.jsp");
%>

<%@ include file="/WEB-INF/templates/classic2.jsp" %>

Now that we have a template we can use it to created end-user pages. Suppose whe have a file named /home.htm with the main content of a welcome page:

<%-- Main Content: /WEB-INF/home-main.jsp --%>

<h1> Welcome to MyCom</h1>

<p>MyCom is a demo website created for the purpose of showing you
how to make use of templates with JSP,
without depending on an extra templating framework.</p>

Assume the template is stored in file templates/mycom-template.jsp. We apply the template to the welcome page by composing the template with the page specific content, as follow:

<%-- Composition Page: home.jsp --%>

<%
request.setAttribute("title", "Welcome to MyCom");
request.setAttribute("body", "/WEB-INF/home-main.jsp");
%>

<jsp:include page="/WEB-INF/templates/mycom-template.jsp" />

A scriptlet is used to define the missing values for the component and string placeholders. This is the the page main content and the title of the page.

Naturally, we could also apply the template to another page:

<%-- Main Content: /WEB-INF/about-main.jsp --%>

<h1> About MyCom</h1>

<p>MyCom is about how simple ideas make a difference.</p>
<%-- Composition Page: about.jsp --%>

<%
request.setAttribute("title", "About MyCom");
request.setAttribute("body", "/WEB-INF/about-main.jsp");
%>

<jsp:include page="templates/mycom-template.jsp" />

Table above shows the file tree for the mycom demo website with two pages using the same JSP template.

+ mycom --> project home
+ web --> application
+ about.jsp --> about composition page
+ home.jsp --> home composition page
+ index.jsp --> site map
+ mycom.css --> CSS stylesheet
+ mycom2.css --> alt. CSS stylesheet
+ META-INF --> standart meta directory
+ WEB-INF --> standart web directory
+ web.xml --> standart application descriptor
+ about-main.jsp --> about page main content
+ home-main.jsp --> home page main content
+ templates --> templating files
+ classic1.jsp --> abstract layout
+ classic2.jsp --> alt. abstract layout
+ header.jsp --> header component
+ footer.jsp --> footer component
+ menu.jsp --> menu component
+ mycom-template.jsp --> template page
+ img --> image directory

File tree for mycom demo web site.

Sample Template

To complete the definition of the template we need to provide the remaining components used by the template. Below, we show a sample header, footer, menu. The CSS file is provided as a external resource.

<%-- Header Component: /WEB-INF/templates/header.jsp --%>
<div id="header">
  <h1> <img src="img/mycom.png" style="vertical-align: middle"/> MyCom </h1>
</div>
<%-- Footer Component: /WEB-INF/templates/footer --%>
<div id="footer">
  <h4>(c) mycom.com</h4>
</div>
<%-- Menu Component: /WEB-INF/templates/menu.jsp --%>

<ul>
  <li><a href="/home.jsp">Home</a></li>
  <li><a href="/about.jsp">About</a></li>
</ul>

Figure above shows how the two end-user web pages appear in the web browser fully composed with the template layout and style. You can notice that the same layout structure shows up in the two pages, and that header, footer and menu components are also shared between components. Style is also shared, since this is already provided by (X)HTML and CSS.

Two pages of MyCom demo site layout with the same template.

Alternative Template

Because we setup the markup for the abstract layout in a dedicate file, it is very easy to experiment with different layouts (e.g. such as when experimenting with different web design or implementing multiple themes). Below, we show an alternative abstract layout suitable for horizontal navigation menus:

<%-- Abstract Layout II: /WEB-INF/templates/classic2.jsp --%> 
<html>
<head>
  <link href="${requestScope.css}" type="text/css" rel="stylesheet" />
  <title> ${requestScope.title} </title>
</head>
<body>
  <div> <jsp:include page="${requestScope.header}" /> </div>
  <div> <jsp:include page="${requestScope.menu}" /> </div>
  <div> <jsp:include page="${requestScope.body}" /> </div>
  <div> <jsp:include page="${requestScope.footer}" /> </div>
</body>
</html>

To change to a different layout solution one needs to change the include directive of the layout in the template file. The css file is also changed to adapt to horizontal menus.

<%-- Template for MyCom Site:
	/WEB-INF/templates/mycom-template.jsp --%> 

<%-- Setup alternative stylesheet --%> 
<% request.setAttribute("css", "mycom2.css"); %>
...
<%-- Include alternative abstract layout --%> 
<jsp:include page="classic2.jsp" />

We could also use a different template file to include the new abstract layout. Additionally, since composition pages point to the template file we would need to make the appropriate change in all composition pages. If we are planning to use a single theme in the web site, it easier to change the single line in the template file with the include directive. On the other hand, if we planning to use themes then with the outlined approach we need to make new composition pages for each theme.

Figure above shows how the two end-user web pages appear in the web browser fully composed with the alternative layout and style.

Two pages of MyCom demo site layout with an alternative template.

Context from Request Parameters

In the solution above, we used request scoped variables to store the location of resources used. An alternative approach is to pass the location of resources as request parameters. Request parameters are usually used to pass user and application data (such as the value of forms elements), but they can also be use for templating. This has the advantage of making value seeting more natural as JSP provides the tag <jsp:param> to set the value of request parameters. This, however, only work for dynamic includes, so we need to always use the tag <jsp:include> and not the directive <%@include%>. The syntax is show below:

<jsp:include page="/WEB-INF/templates/mycom-template-param.jsp" >
  <jsp:param name="title" value="Welcome to MyCom"/>  
  <jsp:param name="body" value="/WEB-INF/home-main.jsp"/>  
</jsp:include>

To access the values of parameter we use the standart variable param in replacement for requestScope. As before, we can use both EL expressions or Java expression to acess the values of request parameters:

<%-- Getting  value of request parameters set with tag <jsp:param> --%>

<%-- Using EL expressions --%>
${param.header}

<%-- Using Java expressions --%>
<%= request.getParameter("header") %>

Below, we show the classic2 layout and the adapted template using request parameters and EL expressions. The template file is the one included above with the sample page.

<%-- Abstract Layout II using request parameters:
	/WEB-INF/templates/classic2-param.jsp --%> 

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <link href="${param.css}" type="text/css" rel="stylesheet" />
  <title> ${param.title} </title>
</head>
<body>
<jsp:include page="${param.header}" />
<jsp:include page="${param.menu}" />
<jsp:include page="${param.body}" />
<jsp:include page="${param.footer}" />

</body>
</html>
<%-- Template for MyCom site using request parameters:
	/WEB-INF/templates/mycom-template-param.jsp --%> 

<jsp:include page="classic2-param.jsp">
	<jsp:param name="css" value="mycom2.css"/>
	<jsp:param name="header" value="header.jsp"/>
	<jsp:param name="menu" value="menu.jsp"/>
	<jsp:param name="footer" value="footer.jsp"/>
</jsp:include>

Comparision to Other Approaches

Configuration of the Application Descriptor web.xml

...todo...

Tiles

...todo...

SiteMesh

...todo...

Summary and Conclusions

I have shown how a build and use layout templates with plain-old JSP, JSTL an EL, without the need for an extra layout framework such as Tiles or SiteMesh. The approach implements the view composite design-pattern, where pages are assembled out of common and page specific parts. The limitation is there is not mechanism to automatically inserted component in pages. Thus for every end-user page, two files need to be provided. One for the main content, and other for composing the main content with the template. This can be mitigate with a simple tool that automatically generates composition pages. An alternative approach is to use the decorator design-pattern. However, JSP by itself does not such mechanism. This requires the use of other elements of Servlet tecnology, such as Servlet and filters. In this regard using templating framework might be useful. Yet other alternative is to apply templates statically, such that no supporting technology for templating is required at request-time.

Resources

Related tutorials by the same author

External References

Acknowlements

If you have any comments or suggestions that you think may improve this document please send an e-mail to the author.

Sponsors (contact to be a sponsor)
(c) Jorge Simão, 2013