Himu\’s Attempt at Blogging

Tidbits from my thoughts

Spring MVC Tutorial – Using Tiles 2

with 7 comments

This post is also based on my previous work:

  1. Spring MVC Tutorial – Hibernate Integration – build a Spring MVC app using Hibernate from the ground up.
  2. Spring MVC Tutorial – Paging through Hibernate and Selection Handling – add table/list browsing support utilizing paging in Hibernate, add a page navigation bar, add checkbox handling against table rows.

Here I will not add any new functionality – just move the view technology to Tiles 2 that comes bundled with Spring complete distribution.

The new completed project is available as ibank-v3.zip.

Till now, I have repeated header/footer/menu code in all the JSP files. Tiles 2 can be used to remove that repetition. Let’s begin.

Required Libraries

I’m using Spring 2.5.6.SEC01. The full distribution comes with the following Tiles 2 jars under lib/tiles:

  • tiles-api-2.0.6.jar
  • tiles-core-2.0.6.jar
  • tiles-jsp-2.0.6.jar

Some Jakarta Commons libraries are mandatory dependencies for Tiles 2. Include them as well from lib/jakarta-commons:

  • commons-beanutils.jar
  • commons-digester.jar
  • commons-logging.jar (already included as a core Spring dependency, so no need to include again)

Caution: Spring 2.5.6 does not work with Tiles 2 2.1.1 onwards. So, we use the old 2.0.6 version supplied with Spring. Spring 3.0 solves this issue.

Typical Tiles 2 without Spring

If I use Tiles 2 without Spring MVC integration then I have two ways to include it in web.xml:

Option 1 – Using a Servlet Definition

<servlet>
    <servlet-name>tiles2</servlet-name>
    <servlet-class>org.apache.tiles.web.startup.TilesServlet</servlet-class>
    <init-param>
        <param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
        <param-value>/WEB-INF/tiles-defs.xml</param-value>
    </init-param>
    <load-on-startup>2</load-on-startup>
</servlet>

Note that a servlet mapping is not required as tiles doesn’t serve any requests directly.

Option 2 – Using a Listener

<listener>
    <listener-class>org.apache.tiles.web.startup.TilesListener</listener-class>
</listener>

<context-param>
    <param-name>org.apache.tiles.impl.BasicTilesContainer.DEFINITIONS_CONFIG</param-name>
    <param-value>/WEB-INF/tiles/defs/tiles-defs.xml</param-value>
</context-param>

Multiple listener and context-param definitions can co-exist in a single web.xml.

In our case, none of the above is required as Spring takes care of setting up Tiles 2.

Defining the Layout and Common Parts

First, create the folder WEB-INF\tiles\layout and create a common layout template (classic.jsp) for the site:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title><tiles:getAsString name="title"/></title>
<link rel="stylesheet" href="css/master.css" type="text/css" />
</head>
<body>
<div id="mask">
    <div id="header">
        <tiles:insertAttribute name="header"/>
    </div>
    <div id="content-wrapper">
        <div id="leftcol-wrapper">
            <div id="leftcol"><tiles:insertAttribute name="menu"/></div>
            <div id="content">
                <tiles:insertAttribute name="body"/>
            </div>
        </div>
    </div>
    <div id=clearfooter"></div>
</div>
<div id="footer" align="center">
    <tiles:insertAttribute name="footer"/>
</div>
</body>
</html>

It’s based on the admin.jsp that I used earlier as a starting point for new JSPs to maintain the layout consistency. Note the tiles taglib at the beginning. The <tiles:…> elements are placeholders that will be filled up by view definitions later on.

The header.jsp and footer.jsp created under tiles folder are very simple serving my purpose.

header.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<table border="0" cellspacing="0" width="100%">
    <tr>
        <td align="center"><h2>iBank – Web Banking Portal</h2></td>
        <td width="50px" align="center" valign="middle">
            <b><font style="size: 1.5em; color: yellow">iBank</font></b>
        </td>
    </tr>
</table>

footer.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
&copy; 2009 Himu

Now, create the tiles/admin folder put menu.jsp in it. This file holds the administration menu.

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<ul>
    <li><a href="<%=request.getContextPath()%>/adminhome.htm">Admin Home</a></li>
    <li><a href="<%=request.getContextPath()%>/createcust.htm">Create New Customer</a></li>
    <li><a href="<%=request.getContextPath()%>/newcustlist.htm">Customer List</a></li>
</ul>

Cleaning the Old JSPs

Now that I’m using Tiles 2, I have to remove the layout code put in each JSP earlier. I’m not going to show each modified JSP. Please look at the attached project. But for a taste of things, here is the new admin.jsp, stripped of all layouts, CSS, and HTML extras:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<center>
<h1>iBank Administration</h1>
<p>Use the menu for navigation.</p>
</center>

I’m also bringing the home page within the template:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<h1 align="center">Welcome to iBank</h1>
<h2 align="center">Your Online Bank Portal</h2>
<p align="center">
    Today is ${today}.<br/>
    <a href="adminhome.htm">Administration Site</a>
</p>

The rest follows a similar pattern.

Writing the View Definitions

Just for demonstration, I’m splitting the definitions in two files – one for normal views, the other for admin site views. The definitions are created in the tiles/defs folder. Here is tiles-defs.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN" "http://tiles.apache.org/dtds/tiles-config_2_0.dtd" >
<tiles-definitions>

    <definition name="site.common" template="/WEB-INF/tiles/layout/classic.jsp">
        <put-attribute name="header" value="/WEB-INF/tiles/header.jsp"/>
          <!–<put-attribute name="title" value=""/>–>
          <!–<put-attribute name="menu" value=""/>–>
          <!–<put-attribute name="body" value=""/>–>
          <put-attribute name="footer" value="/WEB-INF/tiles/footer.jsp"/>
    </definition>

    <definition name="site.home" extends="site.common">
        <put-attribute name="title" value="iBank – Home"/>
        <put-attribute name="menu" value=""/>
        <put-attribute name="body" value="/WEB-INF/jsp/home.jsp"/>
    </definition>
</tiles-definitions>

site.common is the root view definition. It is an abstract definition as title, menu, and body required for classic.jsp are not specified. site.home, for the home page, extends this definition and provides the missing parts.

admin-defs.xml contains the view definitions for the the admin part of the site:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 2.0//EN" "http://tiles.apache.org/dtds/tiles-config_2_0.dtd" >
<tiles-definitions>

    <definition name="admin.common" extends="site.common">
        <!–<put-attribute name="header" value="/WEB-INF/tiles/header.jsp"/>–>
          <!–<put-attribute name="title" value=""/>–>
          <put-attribute name="menu" value="/WEB-INF/tiles/admin/menu.jsp"/>
          <!–<put-attribute name="body" value=""/>–>
          <!–<put-attribute name="footer" value="/WEB-INF/tiles/footer.jsp"/>–>
    </definition>

    <definition name="admin.home" extends="admin.common">
        <put-attribute name="title" value="Administration – Home"/>
        <put-attribute name="body" value="/WEB-INF/jsp/admin/admin.jsp"/>
    </definition>
    <definition name="admin.createcust" extends="admin.common">
        <put-attribute name="title" value="Register New Customer"/>
        <put-attribute name="body" value="/WEB-INF/jsp/admin/newcustomer.jsp"/>
    </definition>

    <definition name="admin.createcust-success" extends="admin.common">
        <put-attribute name="title" value="Customer Registration Successful"/>
        <put-attribute name="body" value="/WEB-INF/jsp/admin/newcustomer-success.jsp"/>
    </definition>

    <definition name="admin.newcustlist" extends="admin.common">
        <put-attribute name="title" value="New/Unauthorized Customers"/>
        <put-attribute name="body" value="/WEB-INF/jsp/admin/newcustlist.jsp"/>
    </definition>

    <definition name="admin.createcust" extends="admin.common">
        <put-attribute name="title" value="Register New Customer"/>
        <put-attribute name="body" value="/WEB-INF/jsp/admin/newcustomer.jsp"/>
    </definition>

</tiles-definitions>

admin.common builds on site.common and specifies the default for menu. It is still abstract (as title and body are not defined) and used as the base for the other admin views.

Modifying the Controllers

The controllers that explicitly mention view names need to be modified as well – just change the old admin/xyz names to admin.xyz as I’ve kept the patterns consistent.

Integrating Tiles 2

I’m using Tiles 2 with Spring MVC. So, no need to modify web.xml. Instead, I have to add a TilesConfigurer in ibank-servlet.xml – the Spring bean definition file for the WebAppliationContext. The steps are as follows:

  1. Tell Spring MVC to configure Tiles 2.
  2. Define a new view resolver for resolving Tiles 2 view names.
  3. Change all necessary view names in the file.

The modified file looks like this:

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

    <!– Tiles 2 –>
    <bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles/defs/tiles-defs.xml</value>
                <value>/WEB-INF/tiles/defs/admin-defs.xml</value>
            </list>
        </property>
    </bean>
    <bean id="simpleUrlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
        <property name="mappings">
            <props>
                <prop key="/home.htm">homePageController</prop>
                <prop key="/adminhome.htm">adminHomePageController</prop>
                <prop key="/createcust.htm">newCustomerController</prop>
                <prop key="/newcustlist.htm">newCustomerListController</prop>
                <prop key="/authorizecust.htm">authorizeCustController</prop>
            </props>
        </property>
    </bean>

    <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
        <property name="order" value="2"/>
    </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="1"/>
    </bean>

    <bean id="homePageController" class="org.himu.ibank.controller.HomePageController"/>

    <bean id="adminHomePageController" class="org.springframework.web.servlet.mvc.ParameterizableViewController">
        <property name="viewName" value="admin.home"/>
    </bean>

    <bean id="newCustomerController" class="org.himu.ibank.controller.NewCustomerController">
        <property name="custRegService" ref="customerRegService"/>
        <property name="formView" value="admin.newcustomer"/>
        <property name="successView" value="admin.newcustomer-success"/>
        <property name="commandName" value="customer"/>
        <property name="commandClass" value="org.himu.ibank.domain.Customer"/>
    </bean>

    <bean id="newCustomerListController" class="org.himu.ibank.controller.NewCustListController">
        <property name="custRegService" ref="customerRegService"/>
    </bean>

    <bean id="authorizeCustController" class="org.himu.ibank.controller.AuthorizeCustController">
        <property name="custRegService" ref="customerRegService"/>
    </bean>
</beans>

Step 1 – The tilesConfigurer bean definition tells Spring MVC to configure Tiles 2 and tells it to use tiles-defs.xml and admin-defs.xml for the view definitions.

Step 2 – The view processor for Tiles 2 in Spring MVC is TilesView. It cannot be used with the InternalResourceViewResolver that I have been using so far. So, I create another view resolver and specify the ordering to Spring MVC so that for any view name, the tilesViewResolver is tried first and then fallback to the default view resolver.

Step 3 – The view names are changed as appropriate.

Done

That concludes the changes for integrating Tiles 2 to the ibank application. Compile, deploy and test. The behavior remains exactly the same.

Advertisements

Written by mhimu

December 9, 2009 at 2:53 pm

Posted in Java, spring

Tagged with , , ,

7 Responses

Subscribe to comments with RSS.

  1. Hello,

    I’m trying this configuration for use multi files for tiles, buth it’s doesn’t work !

    I have this error : Error while resolving definition inheritance: child ‘loginLayout’ can’t find its ancestor ‘generalLayout’

    my bean in my servlet-context.xml

    ${message.bundle.cacheSeconds}

    /WEB-INF/messages/messages
    /WEB-INF/messages/messages_erreurs

    I use spring 3.0 and tiles 2.1.0 or 2.1

    bouquet

    March 8, 2011 at 12:02 am

  2. hi guys for tomcat 5.5 in eclipse
    1.download and paste the following jars in (WEB-INF/lib) folder
    (antlr-2.7.5, antlr-runtime-3.0, asm, cglib-2.2, commons-collections-3.1, commons-dbcp, commons-logging-1.1.1, commons-pool, dom4j-1.6.1, ejb3-persistence, hibernate3, hibernate-annotations, hibernate-commons-annotations, javassist-3.4.ga, javaee, javax.el, jstl-1.1.0, jstl-1.2, jta-1.1, log4j, mysql-connector-java-5.1.15, servlet-api, slf4j-api-1.5.6, slf4j-log4j12-1.5.10, spring, standard)

    2.in web.xml change version to 2.4(replace 2.5 in dtd with 2.4).
    3. in in 3 other xmls (servlet, service, etc)replace javaee to j2ee in dtd.
    4.in the above 3 xmls replace “spring-beans-2.5.xsd” in DTD to “spring-beans.xsd “.

    run tomcat and i think every thing should be working
    good luck
    regards,
    Sachin.S

    Sachin.S

    June 22, 2011 at 3:46 pm

  3. I loved as much as you’ll receive carried out right here. The caricature is attractive, your authored material stylish. nevertheless, you command get got an impatience over that you wish be delivering the following. unwell indubitably come further before once more since precisely the similar nearly a lot ceaselessly inside of case you shield this hike.

    fashion bracket

    October 24, 2011 at 12:05 pm

    • apart from above change you have to include id it is annotaion based integration

      @ParentPackage(value=”tiles-default”)
      public class xyzAction extends ActionSupport {

      @Action(value=”login”, results={
      @Result(name=”SUCCESS”,location=”loginTile” ,type=”tiles” )
      })
      public String execute() throws Exception {
      …………..
      }
      }

      laxmi sidapuram

      October 26, 2012 at 4:26 am

  4. You are so cool! I do not think I’ve truly read anything like that before. So wonderful to find someone with some unique thoughts on this subject. Seriously.. many thanks for starting this up. This site is something that’s needed on the web, someone with some originality!

  5. I’m extremely impressed with your writing skills as well as
    with the layout on your blog. Is this a paid theme or did you
    modify it yourself? Anyway keep up the nice quality writing, it is rare to see a great blog like this one today.

    http://el-penee.es

    September 29, 2013 at 7:35 pm

  6. I appreciate, cause I discovered just what I used to be taking a look for.
    You have ended my four day lengthy hunt! God Bless you
    man. Have a great day. Bye

    Penis enlargement

    September 5, 2014 at 4:37 am


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: