How-to: Using Tiles 2.2.2 with Spring MVC 3.x

In this short tutorial, I’ll explain you how to use the Tiles 2.2.2 templating along with Spring MVC 3.x.

I will only show you how to get startet with Tiles, so I’ll expect that you allready have a Spring MVC project up and running. This is how my project folder structure looks like:

java
webapp
– common
– – top.jsp, bottom.jsp, include.jsp, menu.jsp
– resources
– – css
– – js
– – images
– web-inf
– – views
– – – template.jsp
– web.xml
– tiles.xml
– spring-config.xml

Add the following dependencies to your POM-file:

<dependency>
 <groupId>org.apache.tiles</groupId>
 <artifactId>tiles-core</artifactId>
 <version>2.2.2</version>
 <scope>compile</scope>
 <exclusions>
 <exclusion>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-nop</artifactId>
 </exclusion>
 <exclusion>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 </exclusion>
 <exclusion>
 <groupId>org.slf4j</groupId>
 <artifactId>jcl-over-slf4j</artifactId>
 </exclusion>
 </exclusions>
</dependency>
<dependency>
 <groupId>org.apache.tiles</groupId>
 <artifactId>tiles-template</artifactId>
 <version>2.2.2</version>
 <scope>compile</scope>
</dependency>
<dependency>
 <groupId>org.apache.tiles</groupId>
 <artifactId>tiles-jsp</artifactId>
 <version>2.2.2</version>
 <scope>compile</scope>
</dependency>
<dependency>
 <groupId>org.apache.tiles</groupId>
 <artifactId>tiles-servlet</artifactId>
 <version>2.2.2</version>
 <scope>compile</scope>
</dependency>
<dependency>
 <groupId>org.apache.commons</groupId>
 <artifactId>commons-digester3</artifactId>
 <version>3.2</version>
</dependency>
<dependency>
 <groupId>commons-beanutils</groupId>
 <artifactId>commons-beanutils</artifactId>
 <version>1.8.3</version>
</dependency>
<dependency>
 <groupId>org.slf4j</groupId>
 <artifactId>slf4j-api</artifactId>
 <version>1.6.1</version>
</dependency>

Notice that slf4j is excluded from the tiles-core (version 2.2.2) dependency, which it self uses an old version of slf4j that is incompatible with version 1.6.x used by the apache-commons dependencies. Without the exclusions you’ll end up with this error:

INFO: No Spring WebApplicationInitializer types detected on classpath
22.nov.2012 10:59:30 org.apache.catalina.core.ApplicationContext log
INFO: Initializing Spring root WebApplicationContext
22.nov.2012 10:59:30 org.apache.catalina.core.StandardContext listenerStart
SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
java.lang.NoSuchMethodError: org.slf4j.spi.LocationAwareLogger.log(Lorg/slf4j/Marker;Ljava/lang/String;ILjava/lang/String;Ljava/lang/Throwable;)V
 at org.apache.commons.logging.impl.SLF4JLocationAwareLog.info(SLF4JLocationAwareLog.java:159)
 at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:272)
 at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:111)
 at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4791)
 at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5285)
 at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:150)
 at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:901)
 at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:877)
 at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:633)
 at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:655)
 at org.apache.catalina.startup.HostConfig$DeployDescriptor.run(HostConfig.java:1628)
 at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
 at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
 at java.util.concurrent.FutureTask.run(FutureTask.java:138)
 at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
 at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
 at java.lang.Thread.run(Thread.java:662)
22.nov.2012 10:59:30 com.sun.xml.ws.transport.http.servlet.WSServletContextListener contextInitialized
INFO: WSSERVLET12: JAX-WS context listener initializing
22.nov.2012 10:59:30 com.sun.xml.ws.model.RuntimeModeler getRequestWrapperClass

If you’r getting this error, check your maven dependency tree and exclude slf4j from Tiles, then add the newest version available. Please read this great post that will explain you more about the problem.
http://www.captaindebug.com/2012/01/slf4j-dependencies-and.html#.UNBErYeNu5I
Add the following configuration into your spring-servlet.xml:

<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
 <property name="definitions">
 <list>
 <value>/WEB-INF/tiles.xml</value>
 </list>
 </property>
</bean>
<bean id="viewResolver" class="org.springframework.web.servlet.view.UrlBasedViewResolver">
 <property name="viewClass" value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>

Create a template-file (I named mine template.jsp) in your views folder (should be in /WEB-INF/views/):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %>
<%@ taglib prefix="authz" uri="http://acegisecurity.org/authz" %>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<html>
 <head>
 <title><fmt:message key="application.name"/></title>
 <link rel="stylesheet" type="text/css" href="/resources/css/your.css">
 <script type="text/javascript" src="/resources/scripts/jquery-1.8.2.js"></script>
 </head>
 <body>
 <tiles:insertAttribute name="top" />

 <div id="body_container">
 <tiles:insertAttribute name="body" />
 </div>

 <tiles:insertAttribute name="bottom" />
 </body>
</html>

The example template above can be used to insert a header (in attribute “top”), a body (in attribute “body”) and a footer (in attribute “bottom”). You can name your attributes what ever you like.

Create tiles.xml with the following content and place it in the WEB-INF folder

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

<tiles-definitions>
 <definition name="baseLayout" template="/WEB-INF/views/template.jsp">
 <put-attribute name="top" value="/common/top.jsp" />
 <put-attribute name="bottom" value="/common/bottom.jsp" />
 </definition>
 <definition name="start" extends="baseLayout">
 <put-attribute name="body" value="/tiles/start.jsp" />
 </definition>
</tiles-definitions>

Notice the use of doctype. Without it you’ll get an “no grammer found” exception!
Now, all that is left is creating a Spring Controller that returns a ModelAndView with a reference to a tile-definition. In this example controller, I return the
“start” tile which in referes to the “/tiles/start.jsp” file:

@Controller
public class StartpageController{
 /**
 * Return start page
 *
 * @param model
 * @param request
 * @return
 */
 @RequestMapping(value = "/admin/start", method = RequestMethod.GET)
 public ModelAndView viewStartpage(ModelMap model, HttpServletRequest request) {
 return new ModelAndView("start", model);
 }
}

If you try to return a view with an unknown tile-definition, you’ll get a “HTTP Status 500 – Could not resolve view with name ‘springmvctest’ in servlet with name ‘dispatcher'”.

Links:
http://www.javacodegeeks.com/2011/06/springmvc-3-tiles-222-integration.html
http://tiles.apache.org/

This entry was posted in Java, Spring, Web and tagged , . Bookmark the permalink. Post a comment or leave a trackback: Trackback URL.

Post a Comment

Your email is never published nor shared. Required fields are marked *

*
*

You may use these HTML tags and attributes <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>