Spring 3 and Tiles 2 Integration

Podcastpedia.org makes use of Apache Tiles for its layout. This approach was taken because the website pages share a similar structure. Please read first the Getting started guide and Tiles concepts to have a better understanding of what follows. This post will present how Tiles is integrated with Spring MVC for Podcastpedia.org

Note: Spring is the basic technology used for developing Podcastpedia.org

Necessary artifacts

First of all Tiles jars are required in the classpath. They can be directly downloadded from the official website, but Tiles has also been published to the public Maven repository.

You can use one dependency to download all Tiles supported technologies with the following dependency declaration:

<dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-extras</artifactId>
    <version>2.2.2</version>
</dependency>

The basic Tiles dependency with only servlet support can be added this way:

<dependency>
	<groupId>org.apache.tiles</groupId>
	<artifactId>tiles-servlet</artifactId>
	<version>2.2.2</version>
</dependency>

If you need a dependency to Tiles JSP support, Declare the dependency this way:

<dependency>
    <groupId>org.apache.tiles</groupId>
    <artifactId>tiles-jsp</artifactId>
    <version>2.2.2</version>
</dependency>

Spring application context configuration for Tiles

For better readability the Spring Tiles configuration has been placed in a separate file pcm-tiles.xml :

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

    <!-- Views mapped in views.properties (PDF, XLS classes, and others) -->
    <bean id="contentNegotiatingResolver"
              class="org.springframework.web.servlet.view.ContentNegotiatingViewResolver">
        <property name="order"
                  value="#{T(org.springframework.core.Ordered).HIGHEST_PRECEDENCE}" />
         <property name="favorPathExtension" value="true"/>
        <property name="contentNegotiationManager">
            <bean class="org.springframework.web.accept.ContentNegotiationManager">
                <constructor-arg>
                    <bean class="org.springframework.web.accept.PathExtensionContentNegotiationStrategy">
                        <constructor-arg>
                            <map>
                              <entry key="html" value="text/html"/>
                              <entry key="pdf" value="application/pdf"/>
                              <entry key="xsl" value="application/vnd.ms-excel"/>
                              <entry key="xml" value="application/xml"/>
                              <entry key="json" value="application/json"/>
                              <entry key="atom" value="application/xml"/>
                            </map>
                        </constructor-arg>
                    </bean>
                </constructor-arg>
            </bean>
        </property>
     </bean>
    <bean id="tilesViewResolver"
     class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView" />
        <property name="order" value="#{contentNegotiatingResolver.order+1}" />
    </bean>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
      <property name="basename" value="views"/>
      <property name="order" value="#{tilesViewResolver.order+1}" />
    </bean>

    <!-- Helper class to configure Tiles 2.x for the Spring Framework -->
    <!-- See http://static.springsource.org/spring/docs/3.0.x/javadoc-api/org/springframework/web/servlet/view/tiles2/TilesConfigurer.html -->
    <!-- The actual tiles templates are in the tiles-definitions.xml  -->
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tile-defs/templates.xml</value>
                <value>/WEB-INF/tile-defs/definitions.xml</value>
            </list>
        </property>
    </bean>
</beans>

Of interest are

  • the TilesConfigurer (line 53) entry bean, which simply configures a TilesContainer using a set of files containing definitions (templates.xml and definitions.xml), to be accessed by TilesView instance. This is a Spring-based alternative (for usage in Spring configuration) to the Tiles-provided TilesListener (for usage in web.xml)
    • the tilesViewResolver instance (line 37) which is a org.springframework.web.servlet.View implementation that retrieves the Tiles definitions. The order property and the contentNegotiatingResolver will be discussed in another post.

    Creating and using Tiles pages

    After installing and learning some of Tiles concepts, it’s time to show you how the pages are created for Podcastpedia.org

    Create a template

    Podcastpedia.org uses sort of a classic  layout page structure:

    Template

    Template

    As you can see the layout of the website is made of

    • header which includes the social media connect, language selection logo and search bar
    • navigation bar (menu)
    • content – bulk data (body)
    • footer which includes links to Contact, About Us, Disclaimer pages

    The first step was to create a JSP page that acts as this layout and place it under _/WEB-INF/template/_template.jsp file:

    <!DOCTYPE HTML>
    <%@ include file="/WEB-INF/template/includes.jsp" %>
    
    <%@ page language="java" contentType="text/html; charset=UTF-8"
        pageEncoding="UTF-8" %>
    
    <html>
    	<head>
    		<meta name="google-site-verification" content="xxxxxxxxx" />
    		<title><tiles:insertAttribute name="title" ignore="true"/></title>
    		<meta name="description" content="<tiles:insertAttribute name="page_description" ignore="true"/>">
    		<c:url var="cssURL" value="/static/css/style.min.css"/>
    		<link href="${cssURL}" rel="stylesheet" type="text/css"/>
    		<link rel="icon" href="<c:url value="/static/images/favicon.ico"/>" type="image/x-icon" />
    		<link rel="shortcut icon" href="<c:url value="/static/images/favicon.ico"/>" type="image/x-icon" />
    		<meta charset="utf-8">
    		<meta property="og:image" content="<tiles:insertAttribute name="og_image" ignore="true"/>" />
    		<meta property="og:title" content="<tiles:insertAttribute name="og_title" ignore="true"/>" />
    		<meta property="og:description" content="<tiles:insertAttribute name="og_desc" ignore="true"/>"/>
    		<link rel="stylesheet" href="<tiles:insertAttribute name="jquery_ui_css" ignore="true"/>" />
    	</head>
        <body>
        	<div id="banner">
    			<tiles:insertAttribute name="header" />
    		</div>
    		<div></div>
    		<tiles:insertAttribute name="navigation_bar" />
    		<div></div>
    		<div id="page">
    			<tiles:insertAttribute name="content" />
    		</div>
    		<div></div>
    		<div id="footer_wrapper">
    			<tiles:insertAttribute name="footer" />
    		</div>
    	</body>
    </html>

    You can see highlighted the four attributes  header, navigation_bar (menu), content (body) and footer, which resemble the template layout from the picture.  Besides these there are still some other Tiles attributes, like title, page_description or og_image,  that will get filled when rendering actual pages.

    Create the composing pages

    In this phase I had to create four JSP pages, that will take place of header, navigation_bar (menu), content (body) and footer attributes in the previously created template.

    Create a definition

    A definition is a composition to be rendered to the end user; essentially a definition is composed of a template and completely or partially filled attributes.

    • If all of its attributes are filled, it can be rendered to the end user.
    • If not all of its attributes are filled, it is called an abstract definition, and it can be used as a base definition for extended definitions, or their missing attributes can be filled at runtime.

    Initially I created a /<em>WEB-INF/<em>tile-defs/template</em>.xml,</em> which acts as an abstract definition and is extended by all the other Tiles definitions across the Podcastpedia application:

    <?xml version="1.0" encoding="UTF-8" ?>
    
    <!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.1//EN" "http://tiles.apache.org/dtds/tiles-config_2_1.dtd">
    
    <tiles-definitions>
     ......
        <definition name="defaultTemplate" template="/WEB-INF/template/template.jsp">
            <put-attribute name="header" value="/WEB-INF/template/defaultHeader.jsp" />
            <put-attribute name="navigation_bar" value="/WEB-INF/jsp/navigation_bar/default_navigation_bar.jsp" />
            <put-attribute name="content" value="/WEB-INF/template/defaultContent.jsp"/>
            <put-attribute name="footer" value="/WEB-INF/template/defaultFooter.jsp" />
        </definition>
     ......
    </tiles-definitions>

    Now let’s see some examples of definitions extending the defaultTemplate one defined above. For example the definition rendering the home page  of Podcastpedia.org looks like the following:

    <tiles-definitions>
     ......
    	<definition name="startPage_def" extends="defaultTemplate">
    		<put-attribute name="title" value="Podcastpedia, knowledge to go" />
        	<put-attribute name="page_description" value="Educate yourself with selected podcasts from various domains such as science, technology, education, medicine, people, environment, spirituality and much more..."/>
    		<put-attribute name="navigation_bar" value="/WEB-INF/jsp/navigation_bar/start_navigation_bar.jsp" />
    		<put-attribute name="content" value="/WEB-INF/jsp/start/start_page.jsp"/>
        	<put-attribute name="og_title" value="Podcastpedia, knowledge to go"/>
     	    <put-attribute name="og_desc" value="Educate yourself with selected podcasts from various domains such as science, technology, education, medicine, people, environment, spirituality and much more..."/>
     	    <put-attribute name="og_image" value="http://www.podcastpedia.org/static/images/fb_share.png"/>
    	</definition>
     ......
    </tiles-definitions>

    Note that the Tiles attributes are filled with static values specific to the start page, and there are some attributes from the defaultTemplate (like header and footer) that are not overriden – that means they will be inherited from the defaultTemplate (in the end reuse is one of the advantages of inheritence).

    Let’s see another example. This definition – podcastDetails – is used to render a podcast details page :

    <tiles-definitions>
     ......
        <definition name="podcastDetails" extends="defaultTemplate">
        	<put-attribute name="title" expression="${podcast.title}"/>
     	<put-attribute name="page_description" expression="${podcast.description}"/>
        	<put-attribute name="navigation_bar" value="/WEB-INF/jsp/navigation_bar/podcast_details_navigation_bar.jsp" />
        	<put-attribute name="content" value="/WEB-INF/jsp/podcastDetails.jsp"/>
        	<put-attribute name="og_title" expression="${podcast.title}"/>
     	<put-attribute name="og_desc" expression="${podcast.description}"/>
     	<put-attribute name="og_image" expression="${podcast.urlOfImageToDisplay}"/>
        </definition>
     ......
    </tiles-definitions>

    Notice here you can also use dynamic values for the Tiles attributes – for example the title attribute (line 4) is set dynamically with a value,(${podcast.title}), passed from the controller . If you follow the link – The Naked Scientist Podcast – and inspect the source code or the tab name in your browser, you will notice the title of the page was set to “- The Naked Scientists Podcast – Stripping Down Science”

    Well, this is pretty much all you need to do to integrate Tiles 2 in Spring MVC.

    If you liked this, please show your support by helping us with Podcastpedia.org

    We promise to only share high quality podcasts and episodes.

    Resources

    1. http://tiles.apache.org/
    2. http://www.springsource.org/
    Podcastpedia image

    Adrian Matei

    Creator of Podcastpedia.org and Codingpedia.org, computer science engineer, husband, father, curious and passionate about science, computers, software, education, economics, social equity, philosophy - but these are just outside labels and not that important, deep inside we are all just consciousness, right?

    Using The Java Api For Websocket To Create A Chat Server

    In this post, I’ll use Web sockets to create a tiny chat server using Tyrus, the reference implementation of the Java API for WebSocket (JSR 356). Continue reading