There is a dearth of tutorials which examine Spring MVC with Apache Tiles 3. Most of them allude to this one, which is insufficient. Having recently integrated Tiles 3 into my Spring MVC project, I have decided to make a short tutorial on how to get everything running.
What you need : Apache Tiles 3, Spring Framework 3.2.2 (earlier versions may not support Tiles 3 by default), Spring MVC
Steps :
Add your Tiles dependency to pom.xml (or download the Tiles 3 jar and add to your classpath if you're not using Maven) :
Create a tiles.xml file under your WEB-INF directory :
Create a template.jsp under WEB-INF/tiles. Here's an example :
Extra :
If you require list attribute inheritance (which was implemented as a "fallback" here, and did not work for me at all), then change your tiles.xml to :
Notice that I don't need to have the footer.jsp and meta.jsp in all the WEB-INF/tiles subfolders.
What you need : Apache Tiles 3, Spring Framework 3.2.2 (earlier versions may not support Tiles 3 by default), Spring MVC
Steps :
Add your Tiles dependency to pom.xml (or download the Tiles 3 jar and add to your classpath if you're not using Maven) :
<dependency>
<groupId>org.apache.tiles</groupId>
<artifactId>tiles-extras</artifactId>
<version>3.0.0</version>
</dependency>
Make sure you're using Spring 3.2.2 :<properties>
<java-version>1.6</java-version>
<org.springframework-version>3.2.2.RELEASE</org.springframework-version>
<org.aspectj-version>1.6.9</org.aspectj-version>
<org.slf4j-version>1.5.10</org.slf4j-version>
</properties>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>3.2.2.RELEASE</version>
</dependency>
In your servlet-context.xml (or whatever you named yours) :<bean class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<!--Don't add suffix or prefix like you do with .jsp files-->
<property name="viewClass" value="org.springframework.web.servlet.view.tiles3.TilesView"/>
</bean>
<bean id="tilesConfigurer" class="org.springframework.web.servlet.view.tiles3.TilesConfigurer" >
<property name="definitions">
<value>/WEB-INF/tiles.xml</value>
</property>
</bean>
If you were using the traditional Spring MVC view resolution method with jsp files, your servlet-context.xml might have had something like this :<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/views/" />
<property name="suffix" value=".jsp" />
</bean>
Please remove that, since you're using a new mechanism to resolve views.Create a tiles.xml file under your WEB-INF directory :
<!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>
<definition name="*/*" template="/WEB-INF/tiles/template.jsp">
<put-attribute name="meta" value="/WEB-INF/tiles/{2}/meta.jsp" />
<put-attribute name="header" value="/WEB-INF/tiles/{2}/header.jsp" />
<put-attribute name="body" value="/WEB-INF/tiles/{2}/body.jsp" />
<put-attribute name="footer" value="/WEB-INF/tiles/{2}/footer.jsp" />
</definition>
</tiles-definitions>
Here's the directory structure :Create a template.jsp under WEB-INF/tiles. Here's an example :
<!DOCTYPE HTML>
<%@ taglib prefix="tiles" uri="http://tiles.apache.org/tags-tiles" %>
<html>
<head>
<tiles:insertAttribute name="meta" />
</head>
<body>
<div id="header">
<tiles:insertAttribute name="header" />
</div>
<div id="body">
<tiles:insertAttribute name="body" />
</div>
<div id="footer">
<tiles:insertAttribute name="footer" />
</div>
</body>
</html>
Whatever java controller you're using, make sure that the view you're returning matches the wildcard pattern in tiles.xml e.g., "/index" will match "*/*" in tiles.xml and you can use {2} to get the "index" string and tiles will render the tiles under the tiles/index folder :@Controller
public class IndexController {
@RequestMapping(value = "/", method = RequestMethod.GET)
public ModelAndView indexHandler() {
...
return new ModelAndView("/index", "user", new SomeObject());
}
}
Lastly, you can add your views under the WEB-INF/tiles directory. Remember that you'll need the same jsp files which are described in your tiles.xml file.Extra :
If you require list attribute inheritance (which was implemented as a "fallback" here, and did not work for me at all), then change your tiles.xml to :
<!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>
<definition name="base" template="/WEB-INF/tiles/template.jsp">
<put-attribute name="meta" value="/WEB-INF/tiles/common/meta.jsp" />
<put-attribute name="footer" value="/WEB-INF/tiles/common/footer.jsp" />
</definition>
<definition name="*/*" extends="base">
<put-attribute name="header" value="/WEB-INF/tiles/{2}/header.jsp" />
<put-attribute name="body" value="/WEB-INF/tiles/{2}/body.jsp" />
</definition>
</tiles-definitions>
What this essentially does is use the jsp files from the common folder, so you can avoid copying and pasting the same jsp file over and over again in all your subfolders. My directory structure now looks like this :Notice that I don't need to have the footer.jsp and meta.jsp in all the WEB-INF/tiles subfolders.
Hello Dhruv..Thank you very much for the example.
ReplyDeleteI followed same steps but I am getting below error when start my application..can you please help me with htis?
java.lang.ClassNotFoundException: org.apache.tiles.ArrayStack
That class is not included with Tiles 3. I think you're using Tiles 2.
DeleteThank you for your reply. I double checked all files, nowhere I found tiles2. I have tiles3 jars in lib too.
DeleteI hope you can understand below code.
dispatcher-servlet.xml
-------------------------
/WEB-INF/tiles.xml
Tiles.xml
------------
!DOCTYPE tiles-definitions PUBLIC "-//Apache Software Foundation//DTD Tiles Configuration 3.0//EN" "http://tiles.apache.org/dtds/tiles-config_3_0.dtd"
Here is the error I am getting ( couldn’t paste all)
-------------------------------
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.apache.tiles.request.render.CannotRenderException: ServletException including path '/WEB-INF/jsp/layout.jsp'.
org.apache.tiles.request.render.CannotRenderException: ServletException including path '/WEB-INF/jsp/layout.jsp'.
root cause
javax.servlet.ServletException: java.lang.NoClassDefFoundError: org/apache/tiles/ArrayStack
Sorry..dispatcher-servlet text didn't show
DeleteTiles Inegration -->
bean id="tilesConfigurer"
class="org.springframework.web.servlet.view.tiles3.TilesConfigurer"
/WEB-INF/tiles.xml
/list>
</property
/bean
bean id="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver"
property name="viewClass"
value="org.springframework.web.servlet.view.tiles3.TilesView"
Maybe you should make a new stackoverflow question on it. I think your tiles.xml is probably configured wrongly. Can you try removing "/" from "/WEB-INF/jsp/layout.jsp" so that it looks like "WEB-INF/jsp/layout.jsp" inside your tiles.xml. Again, I would recommend that you create a new stackoverflow question.
ReplyDeleteThank you Dhruv. Sure I will try that and see, else I will create new one.
DeleteCould you send use the source ? doesn't work for me :(
ReplyDeleteThis comment has been removed by the author.
ReplyDeleteEver get the fallback working? I've tried all day and keep getting this exception from the OptionsRenderer:
ReplyDeletejava.lang.IllegalStateException: A matching list-attribute name="my_opts" must be defined.
I put the list attribute in the definitions and referenced it according to the docs, but it doesn't work. Any luck? Here's a snippet of my code in tiles.xml within a definition element:
put-attribute name="meta" value="/WEB-INF/tiles/${options[my_opts]}/meta.jsp
followed by a put-list-attribute name="my_opts" within the same definitions element.
Anyone get this working?
Thanks in advance
Mike
btw you can simply use
ReplyDeleteinstead of UrlBasedViewResolver
In fact this is the same implementation as you defined in xml but looks more clear
I mean you can use
ReplyDeleteorg.springframework.web.servlet.view.tiles3.TilesViewResolver
I used the same eventually today. Thanks for the comment. In the fallback method, there's also a SpringApplicationContext class that no longer exists, so I simply took it out. But I'm guessing that might be the issue. I also cracked open the OptionsRenderer to see where that exception was being thrown, and it appears to be trying to get the list attribute via a class named TilesAccess. Anywho, if no one see's a way around this maybe I can find something on the tiles mail lists or post the question there too. The fallback approach looks pretty neat, but I have yet to find a complete working example using a Spring and Tiles version I'm using, which is Spring 3.2.3.RELEASE and Tiles 3.0.1 if I recall (I'm away from my work computer, so I can't see my pom.xml at the moment).
ReplyDeleteWonder if http://tiles.apache.org/tiles-request/apidocs/org/apache/tiles/request/ApplicationContextWrapper.html
ReplyDeletecould replace SpringApplicationContext because it was deleted in Nov 2012 (See https://fisheye.springsource.org/browse/spring-framework-issues/SPR-8825/src/main/java/org/springframework/web/servlet/view/tiles3).
I'm too tired to think anymore....Time to watch some A-Team reruns...
Hi Dhruv, thanks for your post. Do you know how to be able using tiles to reload only the body everytime a option of the menu is clicked, leaving the header and menu static?
ReplyDeleteThanks in advance
Dhruv, this was very helpful, and it worked the first time. :-)
ReplyDeleteThanks for posting it.
The servlet-context.xml stuff is out of date.
ReplyDeleteIt's correct on the original blog post
http://tech.finn.no/2012/07/25/the-ultimate-view-tiles-3/4/
Hopefully you find that the information you were missing originally on that article (that lead you to write this entry) has since been addressed.
The article link was correct, but the information on tiles3 to spring-3.2 integration is on the second page:
Deletehttp://tech.finn.no/2012/07/25/the-ultimate-view-tiles-3/2/
why dont you put the source so atleast one can see and debug himself.
ReplyDeletei deleted the last one, because it removed the code,.. here again :D
ReplyDeleteHi!!
this worked awesome for me !!!!!!!
thanks!!!
i did some changes:
1-I only needed the body, the header was on common too in my case.
2- i added a third parameter in the tiles config */*/*:
< definition name="*/*/*" extends="base" >
< put-attribute name="body" value="/WEB-INF/views/{2}/{3}.jsp" / >
< / definition >
So i can use many jsp files in the same folder =D
then the controller would return the jsp name too in this way:
return new ModelAndView("/dreamer/registered");//for tiles
>>"registered" is the name of the jsp =D (registered.jsp) under the folder "dreamer"
4- i change the path of jsp files, where i had them at first ("views") this was the part that was removed from the servlet context... so i re-added it from the tiles.xml (i only change the path :D )
... /WEB-INF/tiles/template.jsp to /WEB-INF/views/template.jsp
in this way (we can notice the header.jsp here):
< definition name="base" template="/WEB-INF/views/template.jsp" >
< put-attribute name="meta" value="/WEB-INF/views/common/meta.jsp" / >
< put-attribute name="footer" value="/WEB-INF/views/common/footer.jsp" / >
< put-attribute name="header" value="/WEB-INF/views/common/header.jsp" / >
< / definition >
thanks!!!!!!1
Excellent post!!! Java is most popular and efficient programming language available in the market today. It helps developers to create stunning desktop/web applications loaded with stunning functionalities. JAVA J2EE Training in Chennai | Best JAVA Training institute in Chennai
ReplyDeleteThis technical post helps me to improve my skills set, thanks for this wonder article I expect your upcoming blog, so keep sharing...
ReplyDeleteRegards,
ccna training in Chennai|ccna courses in Chennai|ccna training center in Chennai
Cloud has beome the common word that is being used by most of the professional these day. The reason for relying on this technology is security. Your content too lecture the same. Thanks for sharing this worth able information in here. Keep blogging article like this.
ReplyDeleteHadoop Training Chennai | Big Data Training in Chennai
| Best Hadoop Training in Chennai