Spring Boot Mvc + Apache Tiles Example

By Dhiraj Ray, 18 February,2017  

This article is about spring boot mvc apache tiles integration example.Here we will be creating a spring mvc app with spring boot 1.5 using apache tiles 3 layout. We will be creating different reusable page fragments such as header, body, footer using jsp and assemble them in a single jsp page at runtime using configuration file tiles.xml. We will discuss about the different spring boot mvc maven dependencies required and complete configurations to integrate apache tiles with spring boot mvc. Also, we will check how to make use of ModelAndView attributes in JSP while using apache tiles.

apache tiles logo

Background

All websites have some common layout through out all the pages. For example in most of the website header and footer remain the same whereas the body part keep changing. This is called as composite view pattern. Apache tiles works on the priciple of composite view pattern where you can define your different page fragments such as header, footer, side menus, body seperately and spring tiles will assemble all the fragments into a complete page at runtime.

Apache tiles is a free open-sourced templating framework for modern Java applications. Based upon the Composite pattern it is built to simplify the development of user interfaces.

Project Structure

We have defined controller that will be reponsible to render the dashboard page. All the user interface related pages are inside custom folder ui under webapp directory. The layout directory contains all apache tiles layout and view directory has the specific view pages for each controller.

spring-boot-mvc-apache-tiles-project-structure

Maven Dependencies

spring-boot-starter-parent: provides useful Maven defaults. It also provides a dependency-management section so that you can omit version tags for existing dependencies.

spring-boot-starter-web: includes all the dependencies required to create a web app. This will avoid lining up different spring common project versions.

spring-boot-starter-tomcat: enable an embedded Apache Tomcat 7 instance, by default. We have overriden this by defining our version. This can be also marked as provided if you wish to deploy the war to any other standalone tomcat.

tomcat-embed-jasper: provides support for .jsp file rendering.

tiles-jsp: Include tiles dependencies. We are using tiles 3.

spring-boot-maven-plugin: Provides Spring Boot support in Maven.

pom.xml
<?xml version="1.0" encoding="UTF-8"?> <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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.devglan</groupId> <artifactId>spring-boot-apache-tiles-example</artifactId> <version>0.1.0</version> <packaging>war</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.5.1.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-tomcat</artifactId> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> </dependency> <dependency> <groupId>org.apache.tomcat.embed</groupId> <artifactId>tomcat-embed-jasper</artifactId> </dependency> <dependency> <groupId>org.apache.tiles</groupId> <artifactId>tiles-jsp</artifactId> <version>3.0.5</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>

Spring Bean Configuration

SpringBootServletInitializer enables process used in Servlet 3.0 using web.xml

@SpringBootApplication Equivalent to using @Configuration, @EnableAutoConfiguration and @ComponentScan with their default attributes:

Application.java
package com.devglan.tiles; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.web.SpringBootServletInitializer; @SpringBootApplication public class Application extends SpringBootServletInitializer { private static Class applicationClass = Application.class; public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Override protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { return application.sources(applicationClass); } }

This configuration is responsible to initialize spring based web application. We have implemented WebApplicationInitializer.java to configure the ServletContext programmatically.

ApplicationInitializer.java
package com.devglan.tiles; 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.servlet.DispatcherServlet; public class ApplicationInitializer implements WebApplicationInitializer { public void onStartup(ServletContext container) throws ServletException { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.setServletContext(container); ServletRegistration.Dynamic servlet = container.addServlet("dispatcher", new DispatcherServlet(ctx)); servlet.setLoadOnStartup(1); servlet.addMapping("/"); } }

Following is the tiles configuration. You require to register view class as TilesView.class and also configure the location of tiles configuration file. In our case it is tiles.xml inside directory name ui.

BeanConfig.java
package com.devglan.tiles; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.view.UrlBasedViewResolver; import org.springframework.web.servlet.view.tiles3.TilesConfigurer; import org.springframework.web.servlet.view.tiles3.TilesView; @Configuration public class BeanConfig { @Bean public UrlBasedViewResolver viewResolver() { UrlBasedViewResolver tilesViewResolver = new UrlBasedViewResolver(); tilesViewResolver.setViewClass(TilesView.class); return tilesViewResolver; } @Bean public TilesConfigurer tilesConfigurer() { TilesConfigurer tiles = new TilesConfigurer(); tiles.setDefinitions(new String[] { "/ui/tiles/tiles.xml" }); return tiles; } }

Now its time to define tiles definition. Following is sample tiles.xml for our spring boot app. It works on the principle of inheritance, define your parent layout with certain default attributes and other child layouts extending the parent layout can either use the same layout or override with custom attributes.

In our example the main definition is named as mainLayout which has view name as main.jsp. All the default jsp pages like heder, footer which remain common in all the pages are defined here in main layout with body attribute left blank as this part varies for different pages. In child layout definition dashboard which extends main layout defines the specific body attribute for this particular view. You are free to override the header and footer too in the child layout.

tiles.xml
<tiles-definitions> <definition name="mainLayout" template="/ui/jsp/layout/main.jsp"> <put-attribute name="header" value="/ui/jsp/layout/header.jsp" /> <put-attribute name="body" value="" /> <put-attribute name="footer" value="/ui/jsp/layout/footer.jsp" /> </definition> <definition name="dashboard" extends="mainLayout"> <put-attribute name="body" value="/ui/jsp/view/dashboard.jsp" /> </definition> </tiles-definitions>

By default Spring Boot will serve static content from a directory called /static (or /public or /resources or /META-INF/resources) in the classpath or from the root of the ServletContext. But here we have defined out custom folder structure for static contents, hence it is required to tell Spring boot about how to render static content.

WebConfig.java
package com.developerstack.config; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; @Configuration public class WebConfig extends WebMvcConfigurerAdapter { @Override public void addResourceHandlers(final ResourceHandlerRegistry registry) { registry.addResourceHandler("/*.js/**").addResourceLocations("/ui/static/"); registry.addResourceHandler("/*.css/**").addResourceLocations("/ui/static/"); } }

Following is the controller class. Here we are setting view name as dashboard and it does not mean dashboard.jsp. When spring finds view name as dashboard and view class as TilesView, it looks for the tiles configuration files, in our case tiles.xml, and searches for the definition name as dashboard.

DashboardController.java
package com.devglan.controller; import java.util.Arrays; import java.util.List; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.ModelAndView; import com.devglan.tiles.model.User; @Controller public class DashboardController { @RequestMapping(value = "/dashboard", method = RequestMethod.GET) public ModelAndView dashboard() { ModelAndView model = new ModelAndView(); model.addObject("users", getUsers()); model.setViewName("dashboard"); return model; } private List getUsers() { User user = new User(); user.setEmail("johndoe123@gmail.com"); user.setName("John Doe"); user.setAddress("Bangalore, Karnataka"); User user1 = new User(); user1.setEmail("amitsingh@yahoo.com"); user1.setName("Amit Singh"); user1.setAddress("Chennai, Tamilnadu"); User user2 = new User(); user2.setEmail("bipulkumar@gmail.com"); user2.setName("Bipul Kumar"); user2.setAddress("Bangalore, Karnataka"); User user3 = new User(); user3.setEmail("prakashranjan@gmail.com"); user3.setName("Prakash Ranjan"); user3.setAddress("Chennai, Tamilnadu"); return Arrays.asList(user, user1, user2, user3); } }

Following is the model class with getters and setters.

User.java
package com.devglan.tiles.model; public class User { private String name; private String address; private String email; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } }

Client Side

Following is the main.jsp which will be rendered for every request. All the tiles attributes are defined here and these attributes will be identified at run time.

main.jsp
<%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles"%> <!DOCTYPE html> <html> <head> <title> Spring Boot with Apache Tiles</title> <link href="/bootstrap.min.css" rel="stylesheet"> <script src="/jquery-2.2.1.min.js"></script> <script src="/bootstrap.min.js"></script> </head> <body> <div> <div class="container" style="margin:50px"> <tiles:insertAttribute name="header" /> <tiles:insertAttribute name="body" /> <tiles:insertAttribute name="footer" /> </div> </body> </html>

Now let us define our dashboard.jsp

dashboard.jsp
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <div class="row text-center"><strong> User Details</strong></div> <div class="row" style="border:1px solid green;padding:10px"> <div class="col-md-4 text-center"><strong>Name</strong></div> <div class="col-md-4 text-center"><strong>Email</strong></div> <div class="col-md-4 text-center"><strong>Address</strong></div> </div> <c:forEach var="user" items="${users}"> <div class="row" style="border:1px solid green;padding:10px"> <div class="col-md-4 text-center">${user.name}</div> <div class="col-md-4 text-center" >${user.email}</div> <div class="col-md-4 text-center">${user.address}</div> </div> </c:forEach>
footer.jsp
<h2>This is footer</h2>
header.jsp
<h2>This is header</h2> <hr>

Run Application

1.Run Application.java as a java application.

2. Hit the url as http://localhost:8080/dashboard.Following page will be displayed.

spring-boot-mvc-apache-tiles-example

Conclusion

I hope this article served you that you were looking for. If you have anything that you want to add or share then please share it below in the comment section.

Download the source

References

Apache Tiles Tutorial

tiles.apache.org

Suggest more topics in suggestion section or write your own article and share with your colleagues.

Is this page helpful to you? Please give us your feedback below. We would love to hear your thoughts on these articles, it will help us improve further our learning process.

Further Reading: