Dependency Injection with SiteMesh
Let me start off by saying I think that both SiteMesh and Tiles are great frameworks. I was a long time user and fan of Tiles, and I think it's appropriate for certain situations. However, I've been a heavy user of SiteMesh since it passed the 10 minute test. While most heavy users of SiteMesh (the Atlassian guys come to mind) say that it can do everything that Tiles can do, these features are largely undocumented. This is my attempt to document a cool feature.
In a site I recently helped develop, we needed a couple of features:
- A tabbed menu that highlighted the current tab based on which page you were on.
- A bunch of "panels" on the right sidebar that changed according to the page.
To make this work, we used the meta tag functionality that SiteMesh provides.
Funny side/related note, I just googled for this tag and found this howto, which is similar to this one.
In our pages, we added the meta tags to set the active menu, as well as which panels to show in the sidebar:
<head> <title><fmt:message key="authorList.title"/></title> <meta name="menu" content="Authors"/> <meta name="panels" content="administration,blogs,events"/> </head>
Then, in our decorator, we interpret these separately. First, we used Struts Menu (with Velocity) for the navigation system:
<c:set var="currentMenu" scope="request"> <decorator:getProperty property="meta.menu"/> </c:set> <c:import url="/WEB-INF/pages/menu.jsp"> <c:param name="template" value="/template/menu/tabs.html"/> </c:import>
The menu.jsp page takes "template" as a parameter so we display the same menu links using a different Velocity template (for example, links at the bottom of the page).
<menu:useMenuDisplayer name="Velocity" config="${param.template}" permissions="rolesAdapter">
Then our tabs.html Velocity template uses the "currentMenu" attribute to determine which menu to highlight.
## displayMenu is defined in WEB-INF/classes/globalMacros.vm #macro( menuItem $menu $level ) #set ($title = $displayer.getMessage($menu.title)) #if ($menu.url) #if ($menu.name == $currentMenu) <span class="current"> #end <a href="$!menu.url" title="$title"><span>$title</span></a> #if ($menu.name == $request.getAttribute('currentMenu')) </span> #end #end #end #if ($displayer.isAllowed($menu)) #displayMenu($menu 0) #end
As far as the panel injection goes, that's processed using the following logic in our decorator:
<c:set var="panels"><decorator:getProperty property="meta.panels"/></c:set> <!-- No panels set, use default set of panels --> <c:if test="${empty panels}"><c:set var="panels" value="different,partners"/></c:if> <c:forEach var="panel" items="${panels}"> <c:import url="/WEB-INF/pages/panels/${panel}.jsp"/> </c:forEach>
Since this site used WebWork, the <ww:action> tag made it easy to give each panel independence. That is, each panel could load on its own, supply its own data, and not worry about the data being prepared beforehand. Here's an example:
<%@ include file="/common/taglibs.jsp"%> <h2>Author Blogs</h2> <ww:action name="'authors'" id="authors" namespace="default"/> <div class="item"> <ww:iterator value="#authors.authors" status="index"> <a href="<ww:property value="blog.feedUrl"/>"> <img src="${ctxPath}/images/icons/xml.gif" alt="XML Feed" style="margin-right: 5px; vertical-align: middle"/></a> <a href="<ww:property value="blog.url"/>"><ww:property value="name"/></a> <br /> </ww:iterator> </div>
Of course, now that you can use Tiles with WebWork, Struts, Spring MVC and JSF - you could use Tiles for the injection and SiteMesh for the decoration.
Now if we could just get someone to write a JSF Decorator for SiteMesh, like Erik Hatcher did for Tapestry.
PS: I must suck at math because everytime I try to post out here, this blog always rejects my first math anwser with a "Comment authentication failed!". The second attempt always works. Is this just me?
Posted by Sanjiv Jivan on February 16, 2006 at 07:14 PM MST #
Posted by Sanjv Jivan on February 16, 2006 at 07:15 PM MST #
Posted by Matt Raible on February 16, 2006 at 10:14 PM MST #
Posted by Uri Boness on February 17, 2006 at 11:17 AM MST #
Posted by Sylvain on February 24, 2006 at 03:04 PM MST #
Posted by Bill de hÓra on August 02, 2007 at 11:59 PM MDT #