o7planning

Use Template in Spring MVC with Apache Tiles

  1. Instroduction
  2. What is Apache Tiles?
  3. Preview Application
  4. Create Maven Project
  5. Declare maven & web.xml
  6. Configure Spring MVC
  7. Configuring Apache Tiles
  8. Tiles Layout
  9. JSP Fragments
  10. Spring MVC Controller
  11. Run Application

1. Instroduction

This guide was written based on:
  • Eclipse 4.6 NEON(ok for Eclipse 4.5 MARS)
  • Spring MVC 4.x
  • Apache Tiles 3.x

2. What is Apache Tiles?

Apache Tiles inspired by arranging tiles together to make up the roof.

Your web page is also considered as a roof, it is assembled from the tiles, a tile here is a jsp file (jsp fragment). Apache Titles help you define a template to pair the components (jsp fragments) together to form a web.
See template illustration:
classic.jsp
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
<html>
<head>
<title><tiles:getAsString name="title" /></title>
</head>

<body>
    <table width="100%">
        <tr>
            <td colspan="2">
                <tiles:insertAttribute name="header" />
            </td>
        </tr>
        <tr>
            <td width="20%" nowrap="nowrap">
                 <tiles:insertAttribute name="menu" />
             </td>
            <td width="80%">
                 <tiles:insertAttribute name="body" />
             </td>
        </tr>
        <tr>
            <td colspan="2">
                 <tiles:insertAttribute name="footer" />
            </td>
        </tr>
    </table>
</body>
</html>

3. Preview Application

This is a picture of the site:

4. Create Maven Project

In Eclipse, select "File/New/Other..."
  • File/New/Other...
Select archetype "maven-archetype-webapp".
Enter:
  • Group Id: org.o7planning
  • Artifact Id: SpringMVCTiles
  • Package: org.o7planning.tutorial.springmvctiles
This is the project structure is created:
Make sure that you use Java>= 6.
Project properties:
Do not worry about the error message when the Project has been created. The reason is that you do not declare the Servlet library.
Eclipse create Maven project structure may be wrong. You need to fix it.

5. Declare maven & web.xml

Make sure you are using Servlet API >= 3
web.xml
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xmlns="http://java.sun.com/xml/ns/javaee"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
   id="WebApp_ID" version="3.0">
   
   <display-name>SpringMVCTiles</display-name>
   
</web-app>
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
             http://maven.apache.org/maven-v4_0_0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>org.o7planning</groupId>
    <artifactId>SpringMVCTiles</artifactId>
    <packaging>war</packaging>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringMVCTiles Maven Webapp</name>
    <url>http://maven.apache.org</url>


    <dependencies>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>3.8.1</version>
            <scope>test</scope>
        </dependency>

        <!-- Servlet Library -->
        <!-- http://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>

        <!-- JSP API -->
        <!-- http://mvnrepository.com/artifact/javax.servlet.jsp/jsp-api -->
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.2</version>
            <scope>provided</scope>
        </dependency>


        <!-- Servlet JSP JSTL API -->
        <!-- http://mvnrepository.com/artifact/javax.servlet.jsp.jstl/javax.servlet.jsp.jstl-api -->

        <dependency>
            <groupId>javax.servlet.jsp.jstl</groupId>
            <artifactId>javax.servlet.jsp.jstl-api</artifactId>
            <version>1.2.1</version>
        </dependency>



        <!-- Spring dependencies -->
        <!-- http://mvnrepository.com/artifact/org.springframework/spring-core -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <!-- http://mvnrepository.com/artifact/org.springframework/spring-web -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <!-- http://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>4.3.3.RELEASE</version>
        </dependency>

        <!-- Tiles API -->
        <!-- http://mvnrepository.com/artifact/org.apache.tiles/tiles-api -->
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-api</artifactId>
            <version>3.0.7</version>
        </dependency>


        <!-- Tiles Core -->
        <!-- http://mvnrepository.com/artifact/org.apache.tiles/tiles-core -->
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-core</artifactId>
            <version>3.0.7</version>
        </dependency>

        <!-- Tiles Servlet -->
        <!-- http://mvnrepository.com/artifact/org.apache.tiles/tiles-servlet -->
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-servlet</artifactId>
            <version>3.0.7</version>
        </dependency>

        <!-- Tiles JSP -->
        <!-- http://mvnrepository.com/artifact/org.apache.tiles/tiles-jsp -->
        <dependency>
            <groupId>org.apache.tiles</groupId>
            <artifactId>tiles-jsp</artifactId>
            <version>3.0.7</version>
        </dependency>

    </dependencies>


    <build>
        <finalName>SpringMVCTiles</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.3</version>
                <!-- Must update Maven Project -->
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                </configuration>
            </plugin>
            <!-- Config: Maven Tomcat Plugin -->
            <!-- http://mvnrepository.com/artifact/org.apache.tomcat.maven/tomcat7-maven-plugin -->
            <plugin>
                <groupId>org.apache.tomcat.maven</groupId>
                <artifactId>tomcat7-maven-plugin</artifactId>
                <version>2.2</version>
                <!-- Config: contextPath and Port (Default - /SpringMVCTiles : 8080) -->
                <!--
                     <configuration>
                         <path>/</path>
                         <port>8899</port>
                     </configuration>
                -->
            </plugin>
        </plugins>
    </build>
</project>

6. Configure Spring MVC

SpringWebAppInitializer.java
package org.o7planning.springmvctiles.config;

import javax.servlet.FilterRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.filter.CharacterEncodingFilter;
import org.springframework.web.servlet.DispatcherServlet;

public class SpringWebAppInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext servletContext) throws ServletException {
        AnnotationConfigWebApplicationContext appContext = new AnnotationConfigWebApplicationContext();
        appContext.register(ApplicationContextConfig.class);

        ServletRegistration.Dynamic dispatcher = servletContext.addServlet("SpringDispatcher",
                new DispatcherServlet(appContext));
        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");

        // UtF8 Charactor Filter.
        FilterRegistration.Dynamic fr = servletContext.addFilter("encodingFilter", CharacterEncodingFilter.class);

        fr.setInitParameter("encoding", "UTF-8");
        fr.setInitParameter("forceEncoding", "true");
        fr.addMappingForUrlPatterns(null, true, "/*");
    }

}
If you want Spring to interact with Apache Titles, you need to declare 2 Spring BEAN including viewResolver and tilesConfigurer.
ApplicationContextConfig.java
package org.o7planning.springmvctiles.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.UrlBasedViewResolver;
import org.springframework.web.servlet.view.tiles3.TilesConfigurer;
import org.springframework.web.servlet.view.tiles3.TilesView;

@Configuration
@ComponentScan("org.o7planning.springmvctiles.*")
public class ApplicationContextConfig {

    @Bean(name = "viewResolver")
    public ViewResolver getViewResolver() {
        UrlBasedViewResolver viewResolver = new UrlBasedViewResolver();

        // TilesView 3
        viewResolver.setViewClass(TilesView.class);

        return viewResolver;
    }

    @Bean(name = "tilesConfigurer")
    public TilesConfigurer getTilesConfigurer() {
        TilesConfigurer tilesConfigurer = new TilesConfigurer();

        // TilesView 3
        tilesConfigurer.setDefinitions("/WEB-INF/tiles.xml");

        return tilesConfigurer;
    }

}
WebMvcConfig.java
package org.o7planning.springmvctiles.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@Configuration
@EnableWebMvc
public class WebMvcConfig extends WebMvcConfigurerAdapter {

   
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {

        // Default..
    }

    @Override
    public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
        configurer.enable();
    }
     

}

7. Configuring Apache Tiles

tiles.xml defines complete pages. A complete page is made by different jsp fragments.
/WEB-INF/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 Define -->
   <definition name="base.definition"  
       template="/WEB-INF/layouts/classic.jsp">  
       <put-attribute name="title" value="" />  
       <put-attribute name="header" value="/WEB-INF/basefragments/_header.jsp" />  
       <put-attribute name="menu" value="/WEB-INF/basefragments/_menu.jsp" />  
       <put-attribute name="body" value="" />  
       <put-attribute name="footer" value="/WEB-INF/basefragments/_footer.jsp" />  
   </definition>  

   <!-- Home Page -->
   <definition name="homePage" extends="base.definition">  
       <put-attribute name="title" value="Home Page" />  
       <put-attribute name="body" value="/WEB-INF/bodyfragments/_home.jsp" />  
   </definition>  
     
   <!-- ContactUs Page -->
   <definition name="contactusPage" extends="base.definition">  
       <put-attribute name="title" value="Contact Us" />  
       <put-attribute name="body" value="/WEB-INF/bodyfragments/_contactus.jsp" />  
   </definition>  



</tiles-definitions>

8. Tiles Layout

/WEB-INF/layouts/classic.jsp
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%>
<html>
<head>
<title><tiles:getAsString name="title" /></title>
</head>

<body>
    <table width="100%">
        <tr>
            <td colspan="2">
                <tiles:insertAttribute name="header" />
            </td>
        </tr>
        <tr>
            <td width="20%" nowrap="nowrap">
                 <tiles:insertAttribute name="menu" />
             </td>
            <td width="80%">
                 <tiles:insertAttribute name="body" />
             </td>
        </tr>
        <tr>
            <td colspan="2">
                 <tiles:insertAttribute name="footer" />
            </td>
        </tr>
    </table>
</body>
</html>

9. JSP Fragments

_header.jsp
<div style="background: #E0E0E0; height: 55px; padding: 5px;">
  <div style="float: left">
     <h1>My Site</h1>
  </div>

  <div style="float: right; padding: 10px; text-align: right;">

     Search <input name="search">

  </div>

</div>
_menu.jsp
<div style="padding: 5px;">

   <ul>

       <li><a href="${pageContext.request.contextPath}/">Home</a></li>
       <li><a href="${pageContext.request.contextPath}/contactus">Contact Us</a></li>

   </ul>

</div>
_footer.jsp
<div
  style="background: #E0E0E0; text-align: center; padding: 5px; margin-top: 10px;">
   
  @Copyright o7planning.org
   
</div>
_home.jsp
<h2>Hi All</h2>

This is Home Page
_contactus.jsp
Contact Us: o7planning.org
<br>
Address: ${address}
<br>
Phone: ${phone}
<br>
Email: ${email}

10. Spring MVC Controller

MyController.java
package org.o7planning.springmvctiles.controller;

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

@Controller
public class MyController {

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

    
    @RequestMapping(value = { "/contactus" }, method = RequestMethod.GET)
    public String contactusPage(Model model) {
        model.addAttribute("address", "Vietnam");
        model.addAttribute("phone", "...");
        model.addAttribute("email", "...");
        return "contactusPage";
    }
    
}

11. Run Application

In the first, before running the application you need to build the entire project.
Right-click the project and select:
  • Run As/Maven install
Run configurations:
Enter:
  • Name: Run SpringMVCTiles
  • Base directory: ${workspace_loc:/SpringMVCTiles}
  • Goals: tomcat7:run
Click Run:
In the first run the program will take some minutes, so download the tomcat plugin library in order to run.
Everything was ready:
Run URL: