Looks like this question is seeing tumbleweeds. I've given the problem a lot of though, haven't found any viable solutions so figured I'd write an implementation of an idea that I have, I'm posting this for your comments, tell me if you think it's a s**t idea, if you think it's worthy, I'll post the resultant code.
Firstly, I'm planning to solve this with a simple request-less servlet that loads XML menu file resources (initially just one, but support for more later). A menu include can then useBean
the menus loaded and renders in any way the user wishes, default goal is a simple unordered list, which is fairly common.
So first, my menu might look like the following, it's got provision for security roles, but that might be something as an "added extra" by creating two versions SimpleMenuServlet
and SpringSecurityMenuServlet
or something similar.
<menus>
<menu id='home' path='/home'>
<paths>
<match pattern='/home'/>
</paths>
</menu>
<menu id='administration' path='/admin'>
<allowed-roles>
<role name='admin'/>
</allowed-roles>
<paths>
<match pattern='/admin/**'/>
</paths>
</menu>
<menu id='reports' path='/reports'>
<allowed-roles>
<role name='user'/>
<role name='admin'/>
</allowed-roles>
<paths>
<match pattern='/reports/**'/>
<match pattern='/item/*/reports/**'/>
</paths>
<menu>
</menus>
NOTE: there is no "Text" attibute on menus as this is intended to be returned from resource bundles.
Rendering can now be done with a useBean
from the servlet, or via a custom tag library, which I don't think is really necessary, but who knows.
<ul id="main-menu">
<c:forEach var="item" items="${menu-items}">
<c:choose>
<c:when test="${item.selected && !found}">
<c:set var="menuClass" value="selected"/>
<c:set var="found" value="selected"/>
</c:when>
<c:otherwise>
<c:set var="menuClass" value=""/>
</c:otherwise>
</c:choose>
<li id="${item.id}" class="${menuClass}">
<!-- Using resource bundle to get text, this could be the
servlet/menu item that's responsible to get this instead -->
<a href="${item.path}"><fmt:message key="menu-${item.id}" /></a>
</li>
</c:forEach>
</ul>
So now my reasoning is that I could JAR the servlet and menu beans up, control it through web.xml
with respect to loading menu files and startup etc, then render by any view.
As you can see the core of the menu works by path patterns determining which area you're in, it doesn't handle page linking like faces does, but that's not what I'm intending, I'm looking for a static, configurable, maintainable menu, that neither my views nor my controllers have to have a great deal of knowledge of.