ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


O'Reilly Book Excerpts: Programming Jakarta Struts

Programming Jakarta Struts: Using Tiles, Part 1

Related Reading

Programming Jakarta Struts
By Chuck Cavaness

by Chuck Cavaness

In part 1 in this series of book excerpts on using tiles from Programming Jakarta Struts, learn how to use tiles, and gain an understanding of templates.

Up to this point, not much has been said about how to organize and assemble the content and layout of JSP pages for a Struts application. In many ways, that is outside the scope of the topic of Struts. Many excellent books are available that provide strategies for organizing web content and the layout of pages.

In the Storefront application, we have used two different approaches to assembling web pages. The first approach, sometimes referred to as a straight JSP-based approach, is probably the most familiar to web designers. The JSP pages contain presentation logic along with HTML layout tags; there's no separation of the two. This approach is typically used for smaller, less complicated web applications.

The second approach uses the JSP include directive. It's used by developers for larger web applications, or after they realize how repetitive the first approach can be. If you have spent much time maintaining web applications, you know how frustrating it can be to update a site's look and feel. Using the JSP include directive allows for more reuse, which reduces the total development and maintenance costs.

In This Series

Programming Jakarta Struts: Using Tiles, Part 4
We conclude this book excerpt series on using tiles from Programming Jakarta Struts by showing you how to use definitions. You'll also find coverage on support for internationalization of tiles.

Programming Jakarta Struts: Using Tiles, Part 3
In part 3 in this series of book excerpts on using tiles from Programming Jakarta Struts, learn how to use the tile tag library.

Programming Jakarta Struts: Using Tiles, Part 2
In part two in this series of book excerpts on using tiles from Programming Jakarta Struts, learn how to install and configure tiles, as well as get an overview on tiles.

A third approach, which is introduced in this chapter, describes a far better way to reduce the amount of redundant code a web application contains and, at the same time, allows you to separate the content from the layout better than the first two approaches.

Understanding Templates

Traditional GUI toolkits such as VisualWorks Smalltalk or Java Swing all provide some type of layout manager that dictates how content should be displayed within the frame or window. With typical web sites, the layout can undergo many changes, both small and large, over its lifetime. Using layouts and layout managers can help to encapsulate the physical areas of the pages within an application so that they can be altered with minimal impact to the rest of the application. Unfortunately, the JSP technology does not natively provide any direct support for layouts or layout managers. This is why the template-based approach was invented. The concept of templates is not a new one--it has been around for many years, in one form or another.

To understand how templates can actually simplify a web site's layout, let's compare it with an approach that uses the JSP include mechanism. The current index.jsp page of the Storefront application is shown in Example 14-1.

Example 14-1: The index.jsp page for the Storefront application

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
 
<html:html>
 <head>
 <title><bean:message key="global.title"/></title>
 <html:base/>
 <script language=javascript src="include/scripts.js"></script>
 <link rel="stylesheet" href="stylesheets/format_win_nav_main.css" type="text/css">
 </head>

 <body topmargin="0" leftmargin="0" bgcolor="#FFFFFF">

 <!-- Header information -->
 <%@ include file="include/head.inc"%>

 <!-- Menu bar -->
 <%@ include file="include/menubar.inc"%>

 <!--- Include the special offer -->
 <%@ include file="include/mainoffer.inc"%>

 <!-- Featured items header row -->
 <table width="645" cellpadding="0" cellspacing="0" border="0">
  <tr>   
   <td width="21">
   <html:img height="1" alt="" page="/images/spacer.gif" width="1" border="0"/>
   </td>
   <td width="534">
   <html:img page="/images/week_picks.gif" altKey="label.featuredproducts"/>
   </td>
   <td width="1" bgcolor="#9E9EFF">
   <html:img height="1" alt="" page="/images/spacer.gif" width="1" border="0"/>
   </td>
   <td width="1"  bgcolor="#9E9EFF">
   <html:img height="1" alt="" page="/images/spacer.gif" width="1" border="0"/>
   </td>
   <td width="90" bgcolor="#9E9EFF" align="right">
   <html:img height="1" alt="" page="/images/spacer.gif" width="90" border="0"/>
   </td>
  </tr>
  <tr>
   <td>
   <html:img height="1" alt="" page="/images/spacer.gif" width="21" border="0"/>
   </td>
   <td colspan="4" bgcolor="#9E9EFF">
   <html:img height="1" alt="" page="/images/spacer.gif" width="1" border="0"/>
   </td>
  </tr>
 </table>

 <html:img height="10" alt="" page="/images/spacer.gif" width="1" border="0"/><br>

 <!--- Include the featured items -->
 <%@ include file="include/featureditems.inc"%>

 <!--- Include the copyright statement -->
 <%@ include file="include/copyright.inc"%>
 </body>
</html:html>

Static Versus Dynamic Content

With JSP, there are two different kinds of content to include: static and dynamic. The include directive shown here:

<%@ include file="include/copyright.inc" %>

includes the source of the target page at translation/compile time. Therefore, it's not possible to include runtime content using the include directive. The JSP include directive treats a resource as a static object, and the context of the resource is included literally in the page.

In direct contrast, the include action shown here:

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

handles the resource as a dynamic object. The request is sent to the resource, and the result of the processing is included. Templates use a dynamic approach so that runtime expressions can be evaluated and included.

Although the main page uses the JSP include directive, the layout is mixed with content in the page. For example, notice that the page specifies explicitly that the head.inc include file comes first, then the menubar.inc file, the mainoffer.inc file, and so on, right down to the copyright.inc include at the bottom of the page. For every page that we want to have this particular layout, we need to add the same statements in the same order. If a customer wants the menu along the left side instead of across the top, every page will have to be changed.

The Storefront application uses the JSP include mechanism rather than a straight JSP approach. Although the include mechanism is a step in the right direction because it does reduce redundancy (imagine if we included the copyright content in every page!), it's still less efficient than a template-based approach.

What Is a Template?

A template is a JSP page that uses a JSP custom tag library to describe the layout of a page. The template acts as a definition for what the pages of an application will look like, without specifying the content. The content is inserted into the template page at runtime. One or more pages may use the same template.

TIP: The purpose of a template is to get a consistent look and feel within an application without having to hardcode it for every page. It makes sense that most of the pages will use the same template; however, it's not uncommon to have a different look and feel for a few pages within an application and therefore to require more than one template.

Example 14-2 illustrates a template for the Storefront application.

Example 14-2: A basic template for the Storefront application

<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean"%>
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles"%>

<html:html>
 <head>
  <title><bean:message key="global.title"/></title>
  <html:base/>
 </head>
 <body topmargin="0" leftmargin="0" bgcolor="#FFFFFF">

  <!-- Header page information -->
  <tiles:insert attribute="header"/>

  <!-- Menu bar -->
  <tiles:insert attribute="menubar"/>  

  <!-- Main body information -->
  <tiles:insert attribute="body-content"/>

  <!-- Copyright information -->
  <tiles:insert attribute="copyright"/>
 </body>
</html:html>

Not many new concepts are introduced in the template file in Example 14-2. The first thing that you should notice is that we are using Struts custom tag libraries. The fact that we are using the Tiles tag library as well as the HTML and Bean libraries shouldn't be too shocking; the Tiles tag library is just like any other. We'll talk in detail about the Tiles tag library later in this chapter.

The rest of the page is a mixture of HTML layout tags. You should notice that there's no content included, only insert tags where content will be inserted at runtime. You should already be familiar with the Struts tags shown here, so we won't say anything about them. The insert tag performs a role similar to that of the JSP include directive. It's basically saying that somewhere there's a variable called header, for instance, and that the attribute value of "header" should be passed to the insert tag, and the content that is produced should be inserted right here. The same thing goes for the menubar, body-content, and copyright inserts. We'll explain shortly how the "real" content is substituted for these attributes at runtime.

Notice that this layout is very similar to the one shown in Example 14-1. The only difference is that instead of explicitly including the mainoffer and featureditem includes, as Example 14-1 does, the template file includes a body-content section. This allows us to reuse the template for any page that has this generic format. Once we figure out how to supply the page-specific body content, we can reuse this template over and over again. This one file can then control the layout of multiple pages. If we need to modify the layout of the site, this is the only file we need to change--that's the real power of using a template-based approach.

The last piece of the puzzle is how the header, menubar, body-content, and copyright sections are put together to form the rendered output. The important point to remember is that the JSP page shown in Example 14-2 is the template. You still need JSP pages that supply page-specific content used by the template. For example, if we rewrite the index.jsp page from Example 14-1 using the template from Example 14-2, it will look like the one in Example 14-3.

Example 14-3: The index.jsp page for the Storefront application using a template.

<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>

<tiles:insert page="/layouts/storefrontDefaultLayout.jsp" flush="true">
  <tiles:put name="header" value="/common/header.jsp" />
  <tiles:put name="menubar" value="/common/menubar.jsp" />
  <tiles:put name="body-content" value="/index-body.jsp" /> 
  <tiles:put name="copyright" value="/common/copyright.jsp" />
</tiles:insert>

The first thing to notice in Example 14-3 is that the Tiles tag library is included at the top. Every page (or tile) that needs to use the Tiles tag library must include it with this line:

<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>

Two tags from the Tiles library are used in Example 14-3: insert and put. (The complete set of Tiles tags and their associated attributes are discussed later in this chapter.) You already saw the insert tag in Example 14-2, but it's performing a slightly different function in Example 14-3. Two attributes are being supplied to the insert tag: page and flush. The page attribute informs the tag that this JSP page is using a particular template (or layout, in the Tiles world--layouts also are discussed later in this chapter). We are calling the template from Example 14-2 storefrontDefaultLayout.jsp. The flush attribute informs the controller to flush the page output stream before inserting content into the result page.

The put tag in Example 14-3 answers a question that we asked in the previous section: how does the page-specific content get supplied to the template? As you can see, the attributes for the put tag in this example are name and value. If you compare the values of the different name attributes, you'll see that they match up to the ones that the template file in Example 14-2 expects. When the index.jsp page from Example 14-3 is executed, the template file is processed and dynamically passed the header.jsp, menubar.jsp, index-tile.jsp, and copyright.jsp files from the put tags:

<tiles:insert page="/layouts/storefrontDefaultLayout.jsp" flush="true">
  <tiles:put name="header" value="/common/header.jsp" />
  <tiles:put name="menubar" value="/common/menubar.jsp" />
  <tiles:put name="body-content" value="/index-body.jsp" />
  <tiles:put name="copyright" value="/common/copyright.jsp" />
</tiles:insert>

At runtime, the values of the put tags are dynamically substituted into the template file and processed. The resulting output is what gets displayed to the client.

To wrap up the discussion of templates, here is another page that uses the same template from Example 14-2 but supplies a different body-content. Example 14-4 shows the itemdetail.jsp page.

Example 14-4: The itemdetail.jsp page for the Storefront application.

<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>

<tiles:insert page="../layouts/storefrontDefaultLayout.jsp" flush="true">
  <tiles:put name="header" value="../common/header.jsp"/>
  <tiles:put name="menubar" value="../common/menubar.jsp"/>
  <tiles:put name="body-content" value="../catalog/itemdetail-body.jsp"/>
  <tiles:put name="copyright" value="../common/copyright.jsp"/>
</tiles:insert>

The only difference between the index.jsp page in Example 14-3 and the itemdetail.jsp page in Example 14-4 is the content supplied by the body-content attribute.

TIP: If you are still not convinced of the value of using templates, notice that the index.jsp and itemdetail.jsp pages in Example 14-3 and Example 14-4 do not specify anything about how the content should be laid out. They both reference the storefrontDefaultLayout.jsp file, which has sole responsibility for displaying the content in a prescribed format. If we want to change the layout of the site, we have to modify only the storefrontDefaultLayout.jsp file.

In the next installment, learn how to install and configure tiles

Chuck Cavaness is a graduate from Georgia Tech with degrees in computer engineering and computer science. He has built Java-based enterprise systems in the healthcare, banking, and B2B sectors. He is also the author of two O'Reilly books, Programming Jakarta Struts and Jakarta Struts Pocket Reference.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.