Matt RaibleMatt Raible is a Java Champion and Developer Advocate at Okta. developer.okta.com

The JHipster Mini-Book The JHipster Mini-Book is a guide to getting started with hip technologies today: Angular, Bootstrap, and Spring Boot. All of these frameworks are wrapped up in an easy-to-use project called JHipster.

This book shows you how to build an app with JHipster, and guides you through the plethora of tools, techniques and options you can use. Furthermore, it explains the UI and API building blocks so you understand the underpinnings of your great application.

For book updates, follow @jhipster-book on Twitter.

10+ YEARS


Over 10 years ago, I wrote my first blog post. Since then, I've authored books, had kids, traveled the world, found Trish and blogged about it all.

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.

Posted in Java at Feb 16 2006, 09:57:23 AM MST 6 Comments
Comments:

Cool tip but I'm not sure if this is a form of Dependecy Injection (however I must admit if caught my attention :). I re-read Martin Folwers article on Dependency Injection and I do see how this technique fits the pattern. To me it appears that Sitemesh parses the html returned by web app and interpoltes content from the parsed html with the Sitemesh template. Using some of the retun values present in the meta tags for whatever reason (like highlighting a particular menu item) is just like processing return values of a function and not really a injecting a dependency as explained here : http://martinfowler.com/articles/injection.html

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 01:14 PM MST #

"I do see how this technique fits the pattern." should read "I dont see how this technique fits the pattern."

Posted by Sanjv Jivan on February 16, 2006 at 01:15 PM MST #

You're right, it's certainly not dependency injection, though it is some form of injection. My Tiles to SiteMesh Migration explains it a bit better.

Posted by Matt Raible on February 16, 2006 at 04:14 PM MST #

Pretty cool... Funny I just had the same requirement in my last project but I used a different technique. Basically, I categorize pages using a ViewCategoryHandlerInterceptor (spring) and configure the categories in the application context using url path ant expressions. In the decorator I render different menu?s based on the different categories. I like the meta tag approach a bit more because it's more transparent and it feels better to put the category in the actual page and not in the application context. Thanks for the tip

Posted by Uri Boness on February 17, 2006 at 05:17 AM MST #

This post just encourage me to remove tiles from the map. In our project we used tiles only to have one/more panels per application "module". The migration was less pain in the ass that i first thoughts. Thanks for this usefull entry.

Posted by Sylvain on February 24, 2006 at 09:04 AM MST #

[Trackback] Using Sitemesh and meta tags for menus In "Dependency Injection with SiteMesh", Matt Raible describes a technique using Sitemesh for "a tabbed menu that highlighted the current tab based on which page you were on." Matt's technique a Sitemesh feature...

Posted by Bill de hÓra on August 02, 2007 at 05:59 PM MDT #

Post a Comment:
  • HTML Syntax: Allowed