Tiles


Web applications often require a layout including items or elements appearing on many pages. Think of menus or a shopping cart. Almost all major view technologies include a way to decompose the layout of one HTML page into different parts, which can then be included (sequentially) in one main template. But mostly the main template itself describes what to include. When considering a page that requires a menu besides some other content, for example welcoming the user, we could (using JSPs) do the following:

<html>   <head><title>Welcome</title></head>   <body>     <jsp:include page="menu.jsp"/>     <h1>Welcome <c:out value="${user}"/>!</h1>   </body> </html>

There are a couple of disadvantages to this approach:

  • We can't parameterize the menu. We might, for example, want to highlight a specific option in the menu but we can't indicate that alongside the include directive.

  • If the menu.jsp file changed (it might become a static HTML file, maybe a different view technology is used or, even simpler, the location changes), we would need to change a lot of pages including this file.

With respect to the second drawback, you could argue that using a dynamic inclusion (<jsp:include page="${menu}"/>) we could achieve what we want, but then we have to put the menu attribute in our model somehow, which might involve extra work being done in our controller. Spring has an elegant solution for this problem. Using static attributes, you can dynamically include additional data in your model, independently from the controller.

A somewhat more advanced solution to the problem is Struts Tiles, a template-centric framework. Struts Tiles involves tile definition defined in an XML file together with templates defined in JavaServer Pages or the Velocity Template Language. Here, think of a template as a collection of rectangles on a web page where each box is a tile. It's best to explain things with an example. We'll first create our menu in a file called menu.jsp:

 <tiles:importAttribute name="highlighted"/>      <a href="home.html"   <c:if test="${highlighted == 'home'}"></c:if>>   Home </a>   |  <a href="contact.html"   <c:if test="${highlighted == 'contact'}"></c:if>>    Contact </a>  

You can see we've implemented our menu now using a highlighted attributed that represents either the home menu item or the contact menu item (we'll discuss the importAttribute tag later in this chapter). Using JSTL, we decide what item should be highlighted.

Next, let's implement our template (template.jsp):

<html>   <head><title><tiles:put name="title"/></title></head>   <body>     <tiles:insert name="menu"/>         <tiles:insert name="content"/>   </body> </html>

As you can see, using the tiles:insert tag and the tiles:put tag, we're adding a title, a menu, and a piece called content to the page. The magic involved here is a collection of tiles definitions, defined in an external XML file as shown here:

 <!DOCTYPE tiles-definitions PUBLIC   "-//Apache Software Foundation//DTD Tiles Configuration 1.1//EN"   "http://jakarta.apache.org/struts/dtds/tiles-config_1_1.dtd">      <tiles-definitions>        <definition name="welcome" page="/WEB-INF/jsp/template.jsp">     <put name="title" value="Welcome" type="string"/>     <put name="menu" value="menu-home" type="definition"/>     <put name="content" value="/WEB-INF/jsp/content.jsp" type="page"/>   </definition>        <definition name="menu-home" page="/WEB-INF/jsp/menu.jsp">     <put name="highlighted" value="home"/>   </definition>        <definition mame="menu-contact" extends="menu-home">     <put name="highlighted" value="contact"/>   </definition>      </tiles-definitions> 

In the template JSP, you saw that we're including something called menu and something called content. As you might have noticed, those things are tiles and the tiles definitions file shown defines them. When including <tiles:insert name="menu"/> in our JSP, we're actually including the tile named menu-home because that's the tile we've linked to when defining the tile called welcome. As you can see, we've separated the definition of our templates from the actual implementation and we can also parameterize them by extending already defined tiles and changing attributes of those tiles.

Tiles comes with good documentation so we won't go into more detail on the Tiles definition language and the way to extend, parameterize, and configure tiles. Instead, please refer to the Struts user guide and the specific section on Tiles (http://struts.apache.org/userGuide/building_view.html#includes).

Spring's integration with Tiles consists of a Tiles configuration utility and two Tiles view implementations. The concept of configurers is also used with Spring's support for Velocity and FreeMarker. A configurer typically loads configuration files and sets up the technology Spring integrates with.

Important 

Classes such as the TilesConfigurer and the VelocityConfigurer implement an org.springframework.beans.factory.InitializingBean. All classes implementing this interface and registered in an ApplicationContext will automatically be picked up while loading the context, to allow for initialization to be done.

In the case of Tiles, the configurer loads the definition files and sets up a TilesDefinitionFactory, to be used by the TilesView and the TilesJstlView. The latter is the view class you will have to use for Tiles-based views.

 <bean >   <property name="definitions">     <list>       <value>/WEB-INF/definitions/definitions.xml</value>     </list>   </property> </bean>     <bean >   <property name="viewClass">     <value>org.springframework.web.servlet.view.tiles.TilesJstlView</value>   </property> </bean>

The preceding example shows how to wire up a definitions file in /WEB-INF/definitions and how to use the TilesJstlView to render Tiles-based views. When not in need of JSTL (although we can't imagine why someone would ever not include JSTL in his JSPs), you can also use the TilesView, which doesn't include the localization context for use by JSTL formatting tags.

To render a Tiles view, the only thing you have to do is return the tile definition name from your controller:

protected ModelAndView handleRequestInternal(   HttpServletRequest request, HttpServletResponse response) throws Exception {\   return new ModelAndView("welcome"); }

The Tiles view will automatically search for a definition named welcome and render it. When the welcome definition cannot be found, a ServletException will be thrown. Using a HandlerException Resolver, you let Spring resolve this to a view and render an appropriate response to the client.

Important 

There are many ways to design and set up a request-driven web application using a template structure. Another elegant solution is SiteMesh, which is based on the Decorator pattern. We strongly recommend that you check out SiteMesh (www.opensymphony.com/sitemesh) as well when choosing between technologies to include templates in your application. Although integrating SiteMesh is not necessary (it’s really easy to set it up), integration classes are available. There is a custom SiteMesh factory and Spring-compatible decorators. More information on how to integrate SiteMesh with Spring can be found at http://wiki.opensymphony.com/display/SM/Integration+with+Spring.



Professional Java Development with the Spring Framework
Professional Java Development with the Spring Framework
ISBN: 0764574833
EAN: 2147483647
Year: 2003
Pages: 188

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net