August 27, 2014
Hot Topics:
RSS RSS feed Download our iPhone app

Struts in Action: Developing Applications with Tiles

  • April 16, 2003
  • By Manning Publications Co.
  • Send Email »
  • More Articles »

11.3 Tiles Definitions

In listing 11.3, we saw that even the simplest layout can require a good number of parameters. We also saw that in most cases only one or two of those parameters change from page to page.

What's needed is a way to define all these attributes and properties in a single reusable bundle that could just be overloaded with the parameters that change—which, as it happens, it just what the Tiles Definitions do.

11.3.1 Declaring Definitions

Since they serve similar purposes, writing a Tiles Definition is much like writing a <tiles:insert> tag, as we did in 11.2.2. A Definition requires the following information:

  • A path to the base template file
  • A list of zero or more attributes (name-value couplets) to pass to the template
  • An identifier (or name) for the Definition

As you can see, the real difference between a Definition and a <tiles:insert> tag is that a Definition can be named. But just by adding identity to the feature list, several doors are opened:

  • A Definition can be overloaded by passing additional or replacement attributes when it is deployed.
  • A Definition can be extended by using one Definition as the base for another.
  • A Definition can be reused by storing it in a JSP or loading it from an XML document.
  • A Definition can be the target of a Struts ActionForward.

Let's look at the two ways of specifying a Tiles Definition: with a JSP or via an XML document.

11.3.2 JSP declarations

A quick and easy way to get started with Definitions is to declare them with a JSP. This does not reduce the number of template files your application needs but does allow for reuse through overloading. You can declare a base Definition, and then in other Definitions specify how the new Definition differs from its predecessor. This requires the use of a stub file to deploy the Definition at runtime.

In section 11.3.3, we will look at placing these same Definitions in an XML document and deploying them directly from a Struts ActionForward. Since the underlying process is the same, let's discuss the now-familiar JSP-type declaration first.

The process for using Tiles Definitions with JavaServer Pages includes:

  • Declaring a Definition with a JSP
  • Deploying a JSP-declared Definition
  • Overloading a Definition
  • Reusing Definitions with JSPs

Let's discuss each in turn.

Declaring a Definition with a JSP

Listing 11.6 specifies the same particulars as listing 11.4 but uses a Definition.

Listing 11.6 A simple Definition

<%@ taglib uri="/tags/tiles" prefix="tiles" %><tiles:definition id="definitionName" page="/layouts/myLayout.jsp">  <tiles:put name="title"  value="Hello World" />  <tiles:put name="header" value="/tiles/header.jsp" />  <tiles:put name="footer" value="/tiles/footer.jsp" />  <tiles:put name="menu"   value="/tiles/menu.jsp" />  <tiles:put name="body"   value="/tiles/helloBody.jsp" /></tiles:definition>

The Definition in listing 11.6 would be saved as a bean in the JSP context scope, using id as the attribute key. Like many Struts tags, the <tiles:definition> tag supports a scope property for specifying a certain context (application, session, request, page). The default is page context. This Definition would be available to the rest of this JSP only.

Deploying a JSP-declared Definition

To put a Definition to use, you can use the <tiles:insert> tag, specifying the bean name (Definition ID) and also the scope if needed, as shown in listing 11.7.

Listing 11.7 Deploying a Definition

<%@ taglib uri="/tags/tiles" prefix="tiles" %><tiles:definition id="definitionName" page="/layouts/myLayout.jsp">  <tiles:put name="title"  value="Hello World" />  <tiles:put name="header" value="/tiles/header.jsp" />  <tiles:put name="footer" value="/tiles/footer.jsp" />  <tiles:put name="menu"   value="/tiles/menu.jsp" />  <tiles:put name="body"   value="/tiles/helloBody.jsp" /></tiles:definition><tiles:insert beanName="definitionName" flush="true/>

At startup, Tiles uses the XML element to create a Definition object (or bean) with the id definitionName. At runtime, the <tiles:insert> tag refers to the Definition id through its beanName property.

Overloading a Definition

Once we have declared a Definition, we can refer to it by name and overload some or all of its attributes. To overload an attribute, just specify it again with a new value. To create a new attribute, include a new attribute name and its value. This allows you to create a base Definition and then just specify the changes needed to create a new page, as shown in listing 11.8.

Listing 11.8 Overloading a Definition

<%@ taglib uri="/tags/tiles" prefix="tiles" %><tiles:definition id="definitionName" page="/layouts/myLayout.jsp">  <tiles:put name="title"  value="Hello World" />  <tiles:put name="header" value="/tiles/header.jsp" />  <tiles:put name="footer" value="/tiles/footer.jsp" />  <tiles:put name="menu"   value="/tiles/menu.jsp" />  <tiles:put name="body"   value="/tiles/helloBody.jsp" /></tiles:definition><tiles:insert beanName="definitionName" flush="true" >  <tiles:put name="title"  value="New PageTitle" />  <tiles:put name="body"   value="/tiles/anotherBody.jsp" />  <tiles:put name="extra"  value="/extra.jsp" /></tiles:insert>

Here, after declaring the Definition, our <insert> tag specifies a new page title and a different body, and throws in an extra attribute that was not used in the original Definition. This implies that the layout can manage without this tile but can also display it when provided. A layout can indicate an optional tile using the ignore property. When ignore is set to true, an error will not be reported if the attribute is not present.

This is how the myLayout.jsp from the original Definition would specify the extra tile:

  <tiles:insert attribute="extra" ignore="true" />
Reusing Definitions with JSPs

In the preceding example, we had to repeat the Definition before we could overload any of the attributes. Of course, this is not a very practical approach to reuse. A slightly better approach, shown in listing 11.9, is to declare and reuse Definitions by using a utility page and including that page wherever any of the Definitions are needed.

Listing 11.9 Including a Definition

<%@ taglib uri="/tags/tiles" prefix="tiles" %><%@ include file="definitionsConfig.jsp" %%><tiles:insert beanName="definitionName" beanScope="request" /%>  <tiles:put name="title" value="Another Page" /%>  <tiles:put name="body"  value="/tiles/anotherBody.jsp" /%></tiles:insert%>

The key here is the standard JSP include directive that brings in the file containing our Definitions. The Definitions are created normally; you can use any of the Definitions in the usual way. The example also overloads the title and body attributes to customize the page.

This approach to reuse is fine if you have a small number of Definitions, but it doesn't scale well. Each time the file is included, by default all the Definition objects are re-created, draining performance. This can still be a useful approach during development, since any change to the Definitions will be reflected in the next page load.

In production, one workaround would be to create the Definitions in application scope and protect the block with the Struts <logic:notPresent> tag (or equivalent), as shown in listing 11.10.

Listing 11.10 Including a Definition using <logic:notPresent>

<%@ taglib uri="/tags/struts-logic" prefix="logic" %><%@ taglib uri="/tags/tiles" prefix="tiles" %><logic:notPresent name="definitionName" scope="application"><tiles:definition id="definitionName" page="/layouts/myLayout.jsp">  <tiles:put name="title"  value="Hello World" />  <tiles:put name="header" value="/tiles/header.jsp" />  <tiles:put name="footer" value="/tiles/footer.jsp" />  <tiles:put name="menu"  value="/tiles/menu.jsp" />  <tiles:put name="body"  value="/tiles/helloBody.jsp" /></tiles:definition><%-- ... other definitions ... --%></logic:notPresent>

If the Definitions have already been created and stored in application scope, they will not be created again. Each page still has to include the Definitions, and each page will be looking to see if they exist, but at least they won't be continually re-created.

Tiles offers a better approach to loading and reusing Definitions. The Definitions can be declared and loaded once from an XML document. Internally, Tiles renders the Definitions directly from ActionForwards. This is a truly excellent way to manage Tiles Definitions, which we explore in the next section.

1.0 vs 1.1     Tiles for Struts 1.0 subclasses the ActionServlet to render the Definitions. In Struts 1.1, Tiles subclasses the RequestProcessor to do the same thing.




Page 3 of 9



Comment and Contribute

 


(Maximum characters: 1200). You have characters left.

 

 


Sitemap | Contact Us

Rocket Fuel