Nested Tiles: An Apache Tiles Quick Guide to Nesting Tiles

Apache Tiles is a Java Framework used for the templating of Web Applications. Tiles allows developers to define fragments of pages that are combined to create the whole page based on page definitions. The Tiles framework is often used in conjunction with the Apache Struts Model View Controller (MVC) framework. Below are two solutions on how to nest tile elements.

The Problem

During processing Apache Tiles creates a Tiles Context for each level of tile where the attributes defined are only accessible to that context and not any nested tiles. What this means is that you need to pass attributes defined at the top level down to  the nested or inner tiles.  To illustrate lets assume our web application has 4 main elements:

Header
Menu
Body
Footer

Now lets assume that in for some pages our Body is created by Nesting 2 tiles in it so that instead the page consists of:

Header
Menu
Body Part 1 Body Part 2
Footer

What this would mean is that we would have a layout file that is similiar to:

<tiles:insert attribute="header" />
<tiles:insert attribute="menu" />
<tiles:insert attribute="body"/>
<tiles:insert attribute="footer" />

And that our body page for the 2 elements could be represented as:

<table>
  <tr>
    <td><tiles:insert attribute="part1"/></td>
    <td><tiles:insert attribute="part2"/></td>
  </tr>
</table>

Now how do we get those attributes passed to that nested tile.

Solution #1 Defining Nested Tiles in the Tiles Definition

In this solution we define the inner body tile in the definition page and use that definition as the body for the page. So that we end up with a default layout, a page layout, and the body part definitions in our tiles-defs.xml file. A sample is shown below.

<definition name="gLayout" template="/WEB-INF/tiles/gLayout.jsp">
  <put name="header" value="/WEB-INF/tiles/header.jsp" />
  <put name="menu" value="/WEB-INF/tiles/menu.jsp" />
  <put name="footer" value="/WEB-INF/tiles/footer.jsp" />
</definition>

<!-- define the inner tile -->
<definition name="page.body" template="/WEB-INF/tiles/body.jsp">
  <put name="part1" value="/WEB-INF/page/part1.jsp" />
  <put name="part2" value="/WEB-INF/page/part2.jsp" />
</definition>

<!-- define the page by referencing the nested tile -->
<definition name="editpage" extends="gLayout">
  <put name="body" value="page.body"  type="definition"/>
</definition>

Using this method allows you to easily nest tiles and their attributes without having to worry about tiles context and passing attributes to inner nested tiles. The main drawback to this method is that your tiles definitions file can become extremely large depending on your web application.

Solution # 2 Have the Layout file pass attributes to internal tiles

In this approach we update the layout file to pass attributes from its tiles context into the nested tile.  So that the nested tile does not need to be defined in the tiles definition but instead the page definitions will specify the attributes that are utilized as shown below.

tiles-defs.xml

<definition name="gLayout" template="/WEB-INF/tiles/gLayout.jsp">
  <put name="header" value="/WEB-INF/tiles/header.jsp" />
  <put name="menu" value="/WEB-INF/tiles/menu.jsp" />
  <put name="footer" value="/WEB-INF/tiles/footer.jsp" />
</definition>

<!-- define the page by referencing the nested tile -->
<definition name="editpage" extends="gLayout">
  <put name="body" value="/WEB-INF/page/body.jsp" />
  <put name="part1" value="/WEB-INF/page/part1.jsp" />
  <put name="part2" value="/WEB-INF/page/part2.jsp" />
</definition>

gLayout.jsp

<tiles:insert attribute="header" />
<tiles:insert attribute="menu" />
<tiles:insert attribute="body">
  <tiles:put attribute="part1" beanName="part1" />
  <tiles:put attribute="part2" beanName="part2" />
</tiles:insert>
<tiles:insert attribute="footer" />

We now have successfully passed the attributes defined in the tiles definitions into our nested tile by use of the layout file. Although this approach will minimize the size of your tiles definitions file your layout file will need to be expanded to contain all possible attributes that could be utilized by nested tiles, increasing its size.

Resources

// Tiles //

Comments & Questions

Add Your Comment