Categories: springmvc

Spring 4 MVC+Apache Tiles 3 Example

In this post we will integrate Apache Tiles 3 with Spring MVC 4, using annotation-based configuration. Apache Tiles is a template based, composite view framework: it allows to reuse page pieces across the application, keeping consistent look and feel. Page layouts in general contains several page-fragments like header,footer, menu & content. In a consistent layout, only content changes between page navigation while other page fragments like header,footer & menu remains fixed most of the time.

Tiles allows developers to define these page fragments which can be assembled into complete pages at run time.


Following technologies being used:

  • Spring 4.2.6.RELEASE
  • Apache Tiles 3.0.5
  • Maven 3
  • JDK 1.7
  • Tomcat 8.0.21
  • Eclipse MARS.1 Release 4.5.1

Let’s begin.

Step 1: Create the directory structure

Following will be the final project structure:

Let’s now add the content mentioned in above structure explaining each in detail.

Step 2: Update pom.xml to include required dependencies

<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
 xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">

 <modelVersion>4.0.0</modelVersion>
 <groupId>com.websystique.springmvc</groupId>
 <artifactId>Spring4MVCApacheTiles3Example</artifactId>
 <packaging>war</packaging>
 <version>1.0.0</version>
 <name>Spring4MVCApacheTiles3Example</name>

   <properties>
  <springframework.version>4.2.6.RELEASE</springframework.version>
  <apachetiles.version>3.0.5</apachetiles.version>
 </properties>

 <dependencies>
  <!-- Spring -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>${springframework.version}</version>
  </dependency>
  <!-- Apache Tiles -->
  <dependency>
   <groupId>org.apache.tiles</groupId>
   <artifactId>tiles-core</artifactId>
   <version>${apachetiles.version}</version>
  </dependency>
  <dependency>
   <groupId>org.apache.tiles</groupId>
   <artifactId>tiles-api</artifactId>
   <version>${apachetiles.version}</version>
  </dependency>
  <dependency>
   <groupId>org.apache.tiles</groupId>
   <artifactId>tiles-servlet</artifactId>
   <version>${apachetiles.version}</version>
  </dependency>
  <dependency>
   <groupId>org.apache.tiles</groupId>
   <artifactId>tiles-jsp</artifactId>
   <version>${apachetiles.version}</version>
  </dependency>
  
  <!-- Servlet+JSP+JSTL -->
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>javax.servlet.jsp-api</artifactId>
   <version>2.3.1</version>
  </dependency>
  <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>jstl</artifactId>
      <version>1.2</version>
  </dependency>
  
 </dependencies>

 <build>
  <pluginManagement>
   <plugins>
    <plugin>
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-compiler-plugin</artifactId>
           <version>3.2</version>
           <configuration>
               <source>1.7</source>
               <target>1.7</target>
           </configuration>
       </plugin>
    <plugin>
     <groupId>org.apache.maven.plugins</groupId>
     <artifactId>maven-war-plugin</artifactId>
     <version>2.4</version>
     <configuration>
      <warSourceDirectory>src/main/webapp</warSourceDirectory>
      <warName>Spring4MVCApacheTiles3Example</warName>
      <failOnMissingWebXml>false</failOnMissingWebXml>
     </configuration>
    </plugin>
   </plugins>
  </pluginManagement>
  <finalName>Spring4MVCApacheTiles3Example</finalName>
 </build>
</project>

Apart from usual Spring dependencies, We have also added few dependencies for Apache Tiles 3. Additional dependencies can be added for more advanced tiles usage. Maven Apache-tiles page lists all the dependencies from basic to advanced usages.

Step 3: Configure Tiles

Configure tiles in Spring Application configuration file.

package com.websystique.springmvc.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesViewResolver;


@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "com.websystique.springmvc")
public class AppConfig extends WebMvcConfigurerAdapter{

 /**
     * Configure TilesConfigurer.
     */ @Bean
 public TilesConfigurer tilesConfigurer(){
     TilesConfigurer tilesConfigurer = new TilesConfigurer();
     tilesConfigurer.setDefinitions(new String[] {"/WEB-INF/views/**/tiles.xml"});
     tilesConfigurer.setCheckRefresh(true);
     return tilesConfigurer;
 }

 /**
     * Configure ViewResolvers to deliver preferred views.
     */ @Override
 public void configureViewResolvers(ViewResolverRegistry registry) {
  TilesViewResolver viewResolver = new TilesViewResolver();
  registry.viewResolver(viewResolver);
 }
 
 /**
     * Configure ResourceHandlers to serve static resources like CSS/ Javascript etc...
     */ 
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/static/**").addResourceLocations("/static/");
    }
    
}

Highlights of above configurations are TilesConfigurer & TilesViewResolver. TilesConfigurer simply configures a TilesContainer using a set of files containing definitions, to be accessed by TilesView instances. Definition files are basically XML files containing layout definitions.

In our Spring MVC application, we also need a ViewResolver. Spring comes with a Tiles specific ViewResolver named TilesViewResolver. Once configured, the view names returned from your controller methods will be treated as tiles view and Spring will look for a definition having the same name in definitions XML files.

Step 4: Create tiles definitions

Shown below is the definition file tiles.xml

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

<tiles-definitions>  
 
   <!-- Base Definition -->
   <definition name="base-definition" 
       template="/WEB-INF/views/tiles/layouts/defaultLayout.jsp">  
       <put-attribute name="title" value="" />  
       <put-attribute name="header" value="/WEB-INF/views/tiles/template/defaultHeader.jsp" />  
       <put-attribute name="menu" value="/WEB-INF/views/tiles/template/defaultMenu.jsp" />  
       <put-attribute name="body" value="" />  
       <put-attribute name="footer" value="/WEB-INF/views/tiles/template/defaultFooter.jsp" />  
   </definition>  
 
   <!-- Home Page -->
   <definition name="home" extends="base-definition">  
       <put-attribute name="title" value="Welcome" />  
       <put-attribute name="body" value="/WEB-INF/views/pages/home.jsp" />  
   </definition>  

   <!-- Product Page -->
   <definition name="products" extends="base-definition">  
       <put-attribute name="title" value="Products" />  
       <put-attribute name="body" value="/WEB-INF/views/pages/products.jsp" />  
   </definition>  
      
   <!-- Contact-us Page -->
   <definition name="contactus" extends="base-definition">  
       <put-attribute name="title" value="Contact Us" />  
       <put-attribute name="body" value="/WEB-INF/views/pages/contactus.jsp" />  
   </definition>  
 
</tiles-definitions>

In above definition file, we have defined a base-definition and several other definitions extending base-definition. Other defintions are just overwriting the part they are specialized for. template attribute in definition-block is used to specify the actual layout file. Each of the definition (by name) can be treated as a tiles-view.

Step 5: Create Layouts

In our case we have defined a basic layout [/WEB-INF/views/tiles/layouts/defaultLayout.jsp] pinned with definition using template attribte.

defaultLayout.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ page isELIgnored="false" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>

<html>

<head>
 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
 <title><tiles:getAsString name="title" /></title>
 <link href="<c:url value='/static/css/bootstrap.css' />"  rel="stylesheet"></link>
 <link href="<c:url value='/static/css/app.css' />" rel="stylesheet"></link>
</head>
 
<body>
  <header id="header">
   <tiles:insertAttribute name="header" />
  </header>
 
  <section id="sidemenu">
   <tiles:insertAttribute name="menu" />
  </section>
   
  <section id="site-content">
   <tiles:insertAttribute name="body" />
  </section>
  
  <footer id="footer">
   <tiles:insertAttribute name="footer" />
  </footer>
</body>
</html>

This layout file provides the consistent look-n-feel across your application. If you want to change layout, define a corresponding layout file and attach to the definition using template attribute.

As you can see, we have a header,footer,menu & body. We are using tags-tiles tag library to provide the placeholder within layout file. Attributes specified using insertAttribute will be provided by corresponding definition(or the one extending it).

Step 6: Create views

We have created some default views[used when the extending definition does not overwrite them] and some specific ones.
defaultHeader.jsp

<div>
     <h1>Tiles Demo</h1>
</div>

defaultFooter.jsp

<div>
  Made in this world.
</div>

defaultMenu.jsp

<nav>
 <a href="${pageContext.request.contextPath}/"><img class="logo" src="${pageContext.request.contextPath}/static/img/Linux-icon.png"></a>
 <ul id="menu">
  <li><a href="${pageContext.request.contextPath}/">Home</a></li>
       <li><a href="${pageContext.request.contextPath}/products">Products</a></li>
       <li><a href="${pageContext.request.contextPath}/contactus">Contact Us</a></li>
 </ul>
</nav>

home.jsp

<h2>Welcome to Home page</h2>

products.jsp

<h2>Products page</h2>

contactus.jsp

<h2>Contact Us Page</h2>

Step 7: Create Controller

package com.websystique.springmvc.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;



@Controller
@RequestMapping("/")
public class AppController {

 @RequestMapping(value = { "/"}, method = RequestMethod.GET)
 public String homePage(ModelMap model) {
  return "home";
 }

 @RequestMapping(value = { "/products"}, method = RequestMethod.GET)
 public String productsPage(ModelMap model) {
  return "products";
 }

 @RequestMapping(value = { "/contactus"}, method = RequestMethod.GET)
 public String contactUsPage(ModelMap model) {
  return "contactus";
 }
}

Look at each of these controller methods. The returned value from them is treated as tiles-view [Thanks to TilesViewResolver] and corresponding tiles-definition gets consulted.

Step 8: Create Initializer

package com.websystique.springmvc.configuration;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

 @Override
 protected Class<?>[] getRootConfigClasses() {
  return new Class[] { AppConfig.class };
 }
 
 @Override
 protected Class<?>[] getServletConfigClasses() {
  return null;
 }
 
 @Override
 protected String[] getServletMappings() {
  return new String[] { "/" };
 }

}

Step 9: Build, deploy and Run Application

Now build the war (either by eclipse as was mentioned in previous tutorials) or via maven command line( mvn clean install). Deploy the war to a Servlet 3.0 container . Since here i am using Tomcat, i will simply put this war file into tomcat webapps folder and click on startup.bat inside tomcat/bin directory.

If you prefer to deploy from within Eclipse using tomcat: For those of us, who prefer to deploy and run from within eclipse, and might be facing difficulties setting Eclipse with tomcat, the detailed step-by-step solution can be found at : How to setup tomcat with Eclipse.

Open browser and browse at http://localhost:8080/Spring4MVCApacheTiles3Example/

Click on different menu items to see the content gets changes while preserving the actual look-n-feel.

Download Source Code


References

View Comments

  • Hey, very good example, thanks for that :D
    I have tried to run your own project without changing anything but it keeps giving me 404 - Not Found. I also installed Tomcat according to your example and runs normally but the project don't. Is there anything else I should change on tomcat for it?

  • Even though i am posting this question rather later, it's better to ask. Everything seems to work fine when i imported the zip file in my spring tool suit, the problem arises when i try to add another link on the menu. I have followed every step of yours, but it's saying page not found; are there any steps that i'm missing except than creating a link in the menu, creating my page separately, extending the template view and adding it to the config class controller?

  • when i enter username and password .it is not directing to template ..giving exception

    org.apache.tiles.template.NoSuchAttributeException: Attribute 'title' not found.

  • Hey, i created maven project and used all files but i am getting 404 error. i have same structure But i am not able to find the problem ple help me..

  • Hey there, I like a lot this example but got a 403 error at deploy, not a single page shows, I've exactly the same structure but can't find the problem, also I'm using WebLogic12 plus no errors or trace came up in console. Any hint?

    • Hi Dreko, The code in this post have been tested on different versions of tomcat. I don't have any weblogic setup for the moment. Probably you need to do some basic configuration for any project you want to deploy in weblogic.

  • Hi websystique,
    I have an issue displaying the content of child pages.
    for my case I have parent template like below:

    and then the child :

    so when i go to home page i get this result :

    HomePage

    **** Header ****

    WEB-INF/views/homepage.jsp

    as you see the content of homepage.jsp is not displayed

  • Hi ,
    This is so amazing example to understand . But i want multiple template views like admin views (only admin can see this ) and normal user (any user can see this pages) views but i am not able to do this please help me out .

    for example:
    /WEB-INF/defaultViews/**/tiles.xml

    /WEB-INF/administratorViews/**/tiles.xml

  • This is very helpful for me. If i want to exlude the Materpage in one page like eg. login.jsp how to do that ???

    • Hi Nawaraj, for that you could create another definition [parallel to base-definition] which uses a different layout [let's say a loginLayout.jsp] which only have one fragment instead of 4..

  • Good tutorial, but i Have a problem. When i run the example, the ${pageContext.request.contextPath} is not resolving and i can't see the tux logo. Work if i put the ${pageContext.request.contextPath} in the defaultLayout.jsp but no in the view.

    • Hi Daniel, Does your view is a JSP? EL Expressions ${} works in JSP [not in plain .html files unless there is a mapping provide from html to jsp]. For the example itself, i have rerun this example and the expression is evaluated properly.Do note that i am using it in a jsp.

Share
Published by

Recent Posts

Spring Boot + AngularJS + Spring Data + JPA CRUD App Example

In this post we will be developing a full-blown CRUD application using Spring Boot, AngularJS, Spring Data, JPA/Hibernate and MySQL,…

7 years ago

Spring Boot Rest API Example

Spring Boot complements Spring REST support by providing default dependencies/converters out of the box. Writing RESTful services in Spring Boot…

7 years ago

Spring Boot WAR deployment example

Being able to start the application as standalone jar is great, but sometimes it might not be possible to run…

7 years ago

Spring Boot Introduction + hello world example

Spring framework has taken the software development industry by storm. Dependency Injection, rock solid MVC framework, Transaction management, messaging support,…

7 years ago

Secure Spring REST API using OAuth2

Let's secure our Spring REST API using OAuth2 this time, a simple guide showing what is required to secure a…

8 years ago

AngularJS+Spring Security using Basic Authentication

This post shows how an AngularJS application can consume a REST API which is secured with Basic authentication using Spring…

8 years ago