Problem: I have two identical pages home.jsp and contact.jsp with same structure. They differs only in body content and title. I want to create a Layout page using tiles framework and reuse the code for the two JSPs. The controller framework is yet not decided, it may be Spring MVC 3 or Struts 2.
Solution A: Calling JSP files/views directly from controller/action classes.
I write a single definition in tiles.xml like:
<definition name="baseLayout" template="/WEB-INF/jsp/layout/baseLayout.jsp">
<put-attribute name="title" value="" />
<put-attribute name="header" value="/WEB-INF/jsp/includes/header.jsp"/>
<put-attribute name="body" value="" />
</definition>
Now in baseLayout.jsp:
<html>
<head><title><tiles:insertAttribute name="title"/></title></head>
<body>
<div class="wrapper">
<div class="header"><tiles:insertAttribute name="header"/></div>
<div class="body"><tiles:insertAttribute name="body"/></div>
</div>
</body>
</html>
Now in home.jsp
<tiles:insertDefinition name="baseLayout">
<tiles:putAttribute name="title">
Title for home page
</tiles:putAttribute>
<tiles:putAttribute name="body">
Content for home page
</tiles:putAttribute>
</tiles:insertDefinition>
Similarly for contact.jsp :
<tiles:insertDefinition name="baseLayout">
<tiles:putAttribute name="title">
Title for contact page
</tiles:putAttribute>
<tiles:putAttribute name="body">
Content for contact page
</tiles:putAttribute>
</tiles:insertDefinition>
Solution B: Calling the tiles definition of different JSP files from cotrollers/action classes. This approach requires one tiles definition for each of the JSP file I would be writing. So altogether 3 tiles definitions (one is for baseLayout and other two are for home and contact).
tiles.xml :
<definition name="baseLayout" template="/WEB-INF/jsp/layout/baseLayout.jsp">
<put-attribute name="title" value="" />
<put-attribute name="header" value="/WEB-INF/jsp/includes/header.jsp"/>
<put-attribute name="body" value="" />
</definition>
<definition name="home" extends="baseLayout">
<put-attribute name="title" value="Title for home page" />
<put-attribute name="header" value="/WEB-INF/jsp/home.jsp"/>
</definition>
<definition name="contact" extends="baseLayout">
<put-attribute name="title" value="Title for contact page" />
<put-attribute name="header" value="/WEB-INF/jsp/contact.jsp"/>
</definition>
baseLayout.jsp : Same as **Solution A**
home.jsp : Content for home page
contact.jsp : Content for contact page
I want advice on which one of the above approaches I should stick to.
The second solution is the best way:
You can have independent section in your tiles properties for each
jsp layout.
You can change anytime without effecting other layouts later on
The most traditional way using in struts
First solution:
May cause problems later on with having to edit them with any change
specially when you are deep in the project in advanced levels
More generic approach not suitable for struts/tiles architectural
designs
Solution B is the best approach to implement,
you will have individual style template what you can reuse later if required for other jsp's without messing the code in jsp like Solution A.
As of understanding the second approach is more clear and a common standard to follow.
Solution A helps maintenance in large applications by distributing configuration and also promoting name convention over explicit configuration. Moreover it is conceptually compatible with other templating solutions such as JSF or plain tags. For example see this: JSP tricks to make templating easier?
Think an application with hundreds of controllers and views written by different people over a large period of time. With solution B you will have to face a huge tiles.xml file. Add a slight lack of discipline and view names end up an inconsistent mess and content present inside the configuration (like your example).
Related
In my apache tiles config file, I have a section like this:
<definition name="admin/*/*" extends="adminLayout">
<put-attribute name="key" cascade="true" value="{1}" />
</definition>
Then, in my JSP, I am would like to do some logic on the tile attribute.
Something like:
<c:if test="${key == 'value'}">
// do something
</c:if>
where key comes from the tile attribute.
How can I access this tile attribute inside the expression language?
I have tried
<c:set value="<tiles:insertAttribute name='key'/>" var="theKey"></c:set>
and
<c:if test="${<tiles:insertAttribute name='key'/> == 'value'}">
and both times the raw tiles xml is used as the comparing string - it doesn't get replaced by the attribute.
Use Tiles extras:
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:c="http://java.sun.com/jsp/jstl/core"
xmlns:tiles="http://tiles.apache.org/tags-tiles"
xmlns:tilesx="http://tiles.apache.org/tags-tiles-extras"
version="2.0">
<tilesx:useAttribute id="keyJspVariable" name="key" classname="java.lang.String" />
<c:if test="${keyJspVariable== 'value'}">
// do something
</c:if>
Documentation example: https://tiles.apache.org/framework/tutorial/advanced/list-attributes.html
tiles
<definition name="home" extends="container">
<put-attribute name="title" expression="${modal.title}" />
<put-attribute name="body" value="/WEB-INF/jsp/masters/home.jsp" />
<put-attribute name="view" value="home" />
</definition>
this is my method in controller
#RequestMapping("/home/{linkAddress}")
public String homeDt(
#PathVariable(value="linkAddress") String linkAddress,Model model){
HomeMt homeMt = homeMtService.findByLink(linkAddress);
model.addAttribute("contentOne", homeMt.getContentOne());
model.addAttribute("title", "ronaldo");
model.addAttribute("homeMt", homeMt);
return "home";
}
my problem is that the title value is not coming in the jsp page,
some say that enable the el support but it didn't worked for me.
any help will be appreciated
I've inherited an old application that is using Struts 1.2 Tiles 1. For various annoying reasons I can't upgrade.
I'm not very familiar with Struts, or specifically Tiles in general and I'm trying to do something that makes sense in my head but I can't seem to make work in practice. Here's an example of what I'm trying to accomplish:
<tiles-definition>
<definition name="content-with-sidebar" path="/content_with_sidebar.jsp">
<put name="top" value="" type="string" />
<put name="sidebar" value="/tiles/sidebar.jsp" />
<put name="main" value="" type="string" />
<put name="bottom" value="" type="string" />
</definition
</tiles-definition>
content_with_sidebar.jsp
...
<tiles:insert attribute="top" flush="false" />
<div id="content">
<aside>
<tiles:insert attribute="sidebar" flush="false" />
</aside>
<div id="main">
<tiles:insert attribute="main" flush="false" />
</diV>
</div>
<tiles:insert attribute="top" flush="false" />
...
actual_page.jsp
<tiles:insert definition="content-with-sidebar" flush="false">
<tiles:put name="top" type="string">
<div>Maybe this page has something on the top that isn't the page header</div>
</tiles:put>
<!-- use the default sidebar -->
<tiles:put name="main">
<strong>Current Location:</strong>
<address><h:outputText value="#{locationDesc} #{zipCode}" /></address>
<!-- Some more dynamic jsp markup -->
</tiles:put>
<!-- This one doesn't have anything extra on the bottom -->
</tiles:insert>
This almost works but the dynamic bits get rendered above and outside the <tiles:insert> and the plain strings go where they should. I understand now, after much searching, that <tiles:put> in this, er, context, is expecting a plain ole string.
Is there a pattern to accomplish what I want with dynamic context?
As it stands I'm having to create another jsp file to be referenced by the <tiles:put> tag. i.e.
<tiles:put name="main" value="/actual_page_body.jsp" />
I'd rather not have to create an additional file when one would do. Any advice would be helpful.
With tiles, when the definition is rendered (content-with-sidebar in your code), the jsp corresponding to the 'path' attribute (/content_with_sidebar.jsp) will be invoked. All other jsps have to be manually invoked using a <tiles:insert>. What tiles provides you is a way to configurationally invoke them as definition attributes.
I make insert in JSP (dogovorInfo.jsp) code (with Apache Tiles):
<t:insertAttribute name="${transportType}" />
In view.xml I define:
<tiles-definitions>
<definition name="dogovorInfo" template="/WEB-INF/views/dogovorInfo.jsp">
<put-attribute name="13" value="Auto" />
</definition>
<definition name="Auto" template="/WEB-INF/views/dogovorInfo/Auto.jsp" />
</tiles-definitions>
I have a ArrayList of objects in dogovorInfo.jsp, how send one object to Auto.jsp from dogovorInfo.jsp
The only way you could do is use some implicit objects (request, session) for storing the objects & then forward it to next jsp.
Is it possible to access the Apache Tiles definition name inside a ViewPreparer?
just add the attribute into the xml, eg
<definition name="t.*" extends="t.container">
<put-attribute name="body" value="/WEB-INF/jsp/{1}.jsp"/>
<put-attribute name="title" expression="${song.title} - ${song.author} in ${jukebox.name}"/>
<put-attribute name="view" value="t.{1}"/>
</definition>