|
DEVELOPER: Struts
Reuse Tiles and Simplify UI
By James Holmes
Simplify and enhance Struts JSP development with Tiles.
JavaServer Pages (JSP) technology supports application object reuse through includes, which allow other files (including other JSPs) to be sourced into a JSP file either at compile time or dynamically at application runtime. This is great for abstracting common elements of pages such as headers, footers, and menus into reusable chunks that can be used by several files.
Includes are powerful and save time, but they still create potential for a great deal of element duplication. Each JSP file that sources in common elements duplicates the include definitions. If the names of files being included change, each of the files that references them (using includes) must also be updated.
The Tiles framework was created to address this limitation and to enhance the Struts framework. Tiles extends the concept of reuse via includes by allowing you to define layouts (or templates) and then specify how the layouts are populated with content.
With the JSP include paradigm, each JSP specifies its layout and explicitly populates that layout via includes. Most JSP layouts are identical, sourcing in the same files in the same places and then including only one section of unique content (body content). With Tiles, you define a master layout JSP that specifies each of the includes that fill in that layout, and then you define which content should fill in the layout, using an external configuration file. For example, suppose you have a typical Web site layout: a header at the top of the page, a menu on the left, body content in the middle, and a footer at the bottom. If you implement this layout using only JSP includes, each JSP with this layout has to explicitly include the header, menu, and footer sections as well as the body content of the page. The only unique part of the page is the body content. If you implement this layout with Tiles, however, you will create one JSP that includes the header, menu, and footer and you will dynamically include the body content, based on an attribute passed to the layout that indicates which JSP includes the body content. This Tiles layout can then be reused over and over for as many pages as you'd like, and
the only thing your content JSPs have
to contain is the specific, unique body content that goes in the middle of a page.
Adding Tiles to Your Application
Now that you've seen the benefits of using the Tiles framework, here are the steps necessary for adding Tiles to your Struts application:
- Add the Tiles Tag Library Descriptor (TLD) file to the application.
- Create layout JSPs.
- Update existing JSPs to use layouts.
- Create a tiles-defs.xml file.
- Update forward definitions in and add the Tiles plug-in to the struts-config.xml file.
- Repackage and run the updated application.
The following sections go through each step of the process in detail.
Add the Tiles TLD file to the application. The first step in updating your Struts application to use Tiles is to add the Tiles TLD file to the application. This is necessary so that JSPs can use the Tiles Tag Library, which allows you to work with Tiles layouts in JSPs. To add the Tiles TLD file to the application, copy the struts-tiles.tld file from the Struts distribution's lib directory (for example, c:\java\jakarta-struts-1.1\lib) to your application's /WEB-INF/tlds directory. Next, add an entry for the TLD in your application's Web deployment descriptor file, web.xml, and register the Tiles TLD as follows:
<taglib>
<taglib-uri>
/WEB-INF/tlds/struts-tiles.tld
</taglib-uri>
<taglib-location>
/WEB-INF/tlds/struts-tiles.tld
</taglib-location>
</taglib>
You can now reference the TLD from your JSPs by using the following:
<%@ taglib
uri="/technology/WEB-INF/tlds/struts-tiles.tld"
prefix="tiles" %>
Create layout JSPs. Now that you have registered the Tiles TLD, create the layout JSPs. The layout in Listing 1 illustrates the basic concepts of Tiles. This layout is based on the structure of your application's existing pages.
Note that the body content of the layout page in Listing 1 is in boldface text. This content differs for each distinct page. The rest of the page, however, will be consistent across several pages, thus allowing its abstraction into a general-purpose layout.
Three JSP filesmainLayout.jsp, header.jsp, and footer.jspmake up the layout. The mainLayout.jsp file is shown here:
<%@ taglib
uri="/technology/WEB-INF/tlds/struts-tiles.tld"
prefix="tiles" %>
<html>
<head>
<title>
<tiles:getAsString name="title"/>
</title>
</head>
<body>
<tiles:insert attribute="header"/>
<tiles:insert attribute="body"/>
<tiles:insert attribute="footer"/>
</body>
</html>
This JSP defines the layout's template and is used to source in the other layout JSPs as well as the body content. The body content and other layout JSPs are sourced in with <tiles:insert> tags. These tags specify the names of attributes defined in the Tiles configuration file whose values are the names of the
JSPs that should be inserted into the
JSP at runtime. Note the use of the <tiles:getAsString> tag. This tag works similarly to the <tiles:insert> tag, but instead of using the specified attribute's value as the name of a page to include,
it uses it as a literal string. This approach is useful for dynamically inserting into a layout small pieces of content that don't warrant their own include file.
The following are the header and footer layout JSPs:
header.jsp
<font size="+1">
ABC, Inc. Human Resources Portal
</font><br>
<hr width="100%" noshade="true">
footer.jsp
<hr width="100%" noshade="true">
Copyright © ABC, Inc.
These header and footer JSPs are
quite basic and do not contain much HTML. The content of these JSPs
could have been placed directly in the mainLayout.jsp file, and content pages would still have had to contain only the body content of the page. However, breaking the pages up into smaller chunks allows for more flexibility in how layouts are used. If you need some pages to have a custom header and footer and others to use the standard ones, separating the header and footer into discrete chunks allows you to do that. You simply define values for the header and footer attributes at the layout level, and each page that wants a custom header, footer, or both overrides the necessary attributes with new values at the page level.
Update existing JSPs to use layouts. After you create the layout JSPs, update the application's original JSPs to contain only the body content of their pages. To do this, remove the common layout pieces from the original pages. Listing 2 shows an updated example page containing only body content.
The updated page in Listing 2 no longer contains the header or footer portions of the content. At runtime, the layout JSPs surround the contents of this updated page with the common layout content to create the complete page.
Create a tiles-defs.xml file. There are two ways to declare Tiles layouts:
- With Tiles tags in a master JSP that gets included in each of the layout JSPs
- By declaring them in an XML configuration file
The following example uses the configuration file option, because it is the more flexible and easier-to-maintain option. Listing 3 shows the tiles-defs.xml file that declares the layouts. This file should be placed inside your application's /WEB-INF/ folder.
There are two Tiles definitions in this tiles-defs.xml file. The first definition in the file declares a layout named main.layout. Generally, layout definitions specify the template for a page and the list of attributes whose values will be used to fill in the template. Page definitions extend layout definitions and provide values for the attributes defined in the extended layout.
Note that the first definition in Listing 3main.layoutdefines
four attributes with put tags. These attributes will be available to the layout JSP specified by the path attributemainLayout.jsp. This layout JSP uses these attributes to supply the locations of its content. Additionally, attributes can be used to supply literal strings, as is the case with the title attribute. This attribute is used by mainLayout.jsp so it can have a dynamic title based on the value set by page definitions that extend the layout definition.
The second definition in the tiles-defs.xml file in Listing 3 declares a page definition named search.page. This definition extends the main.layout layout definition and supplies values for the attributes that don't have values in the layout definition. This definition can override any of the attributes in the layout definition, but only the title and body attributes are overridden in this example.
Update forward definitions in and add the Tiles plug-in to the struts-config.xml file. After you create the Tiles configuration file, update your application's struts-config.xml file to point to Tiles definitions instead of pointing directly to JSPs for each of the pages that has been converted to use Tiles. Also add the Tiles plug-in to the struts-config.xml file.
Without Tiles, forward and action definitions point directly to JSPs. With Tiles, they point to the page's definition in the Tiles configuration file. For example, before, the application's search action pointed directly to search.jsp, as follows:
<action
path="/technology/search"
type="com.jamesholmes.minihr
.SearchAction"
name="searchForm"
scope="request"
validate="true"
input="/technology/search.jsp"/>
However, with Tiles, the action points to the search page's Tiles definition, as follows:
<action
path="/technology/search"
type="com.jamesholmes.minihr
.SearchAction"
name="searchForm"
scope="request"
validate="true"
input="search.page"/>
For all forward and action definitions in your Struts configuration file that make use of Tiles, replace the JSP references with the appropriate Tiles page definition references, as in this example.
To add the Tiles plug-in to the application, add the following snippet to your struts-config.xml file:
<!-- Tiles Configuration -->
<plug-in className=
"org.apache.struts.tiles.TilesPlugin">
<set-property property=
"definitions-config"
value="/technology/WEB-INF/tiles-defs.xml"/>
</plug-in>
This causes Struts to load the Tiles plug-in at application startup. Note that the Tiles configuration file is specified with the set-property tag. You can specify multiple configuration files with this tag by providing a comma-delimited list of files.
Listing 4 shows a Struts configuration file in its entirety. The sections that have changed or been added are boldfaced.
Repackage and run the updated application. Because no Java code was modified during this process, it's not necessary to recompile your application. However, several files have been added and a few modified, so the application will need to be repackaged and redeployed before it is run. Once you have your updated application running, everything should work as it did before, but now you can add new pages and make global changes to the application with minimal effort.
Conclusion
The Tiles framework adds a great deal
of value to the core Struts framework by providing a powerful templating system that promotes reuse. You can save time and enhance your Struts application development by using the Tiles framework with your JSP application.
James Holmes (james@jamesholmes.com) is an independent Java consultant and committer on the Struts project. He is the author of Struts: The Complete Reference and coauthor of The Art of Java (both from McGraw-Hill/Osborne).
|