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

  • الأنابيب الحرارية والمقاومة للحرارة في العراق في مصنع إيليت بايب في العراق، نفتخر بتقديم الأنابيب الحرارية والمقاومة للحرارة بأعلى جودة. تم تصميم هذه الأنابيب لتحمل درجات الحرارة القصوى والبيئات القاسية، مما يجعلها مثالية لمجموعة متنوعة من التطبيقات الصناعية والتجارية. تم تصنيع أنابيبنا الحرارية لتقديم أداء استثنائي ومتانة، مما يضمن موثوقية طويلة الأمد حتى في أكثر الظروف تطلبًا. كأحد أفضل المصانع وأكثرها موثوقية في العراق، يضمن مصنع إيليت بايب أن جميع الأنابيب الحرارية والمقاومة للحرارة تلتزم بالمعايير الصارمة وتقدم جودة فائقة. لمزيد من المعلومات حول منتجاتنا، قم بزيارة موقعنا على الإنترنت: elitepipeiraq.com.

  • You have been working hard, and you've created beautiful things. The visual presentation is elegant, and the written content is top-notch. Despite the fact that you appear concerned about the possibility of delivering something that may be considered questionable, I believe that you will be able to resolve this problem quickly.

  • 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

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,…

8 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…

8 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…

8 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,…

8 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