1) client file - index.xhtml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html"
template="/templates/template.xhtml">
<ui:define name="title">Page Title</ui:define>
<ui:define name="body">Page Body</ui:define>
</ui:composition>
Here it is using the template.xhtml as the template, then define 2 elements "title" and "body" to pass to template.xhtml.
2) template file - template.xhtml:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
<title><ui:insert name="title">Title</ui:insert></title>
<ui:include src="/templates/header.xhtml"/>
</h:head>
<h:body>
<div id="col2" class="clearfix">
<div id="col2a">
<ui:insert name="body">Body</ui:insert>
<ui:include src="/templates/footer.xhtml"/>
</div>
<div id="col2b">
<div id="nav-container">
<ul id="nav-main">
<ui:include src="/templates/submenu.xhtml">
<ui:param name="submenu" value="#{sessionSupport.menuService.getSubMenu(currentSectionUrl)}" />
<ui:param name="level" value="1" />
</ui:include>
</ul>
</div>
</div>
</div>
</h:body>
</html>
The two "ui:insert" are the place-holders for page title and body, which are provided from the client file (index.xhtml); "ui:include" pieces are convenient to include a few html snippets to make the code clean and neat. Among them submenu.xhtml is the most interesting one.
3) self inclusive snippet file - submenu.xhml:
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
xmlns:ui="http://java.sun.com/jsf/facelets"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:c="http://java.sun.com/jsp/jstl/core">
<c:set var="url" value="#{sessionSupport.breadCrumbs[level+1].url}"/>
<c:set var="requestURI" value="#{sessionSupport.requestURI}" />
<c:forEach items="#{submenu}" var="menuItem" varStatus="status">
<c:choose>
<c:when test="#{sessionSupport.menuService.isSelf(menuItem, requestURI)}">
<li class="active"><a href="#{menuItem.url}">#{menuItem.name}</a>
<ul>
<ui:include src="/templates/submenu.xhtml">
<ui:param name="submenu" value="#{sessionSupport.getSubMenu(
url
)}"/>
<ui:param name="level" value="#{level+1}" />
</ui:include>
</ul>
</li>
</c:when>
<c:otherwise>
<li><a href="#{menuItem.url}">#{menuItem.name}</a></li>
</c:otherwise>
</c:choose>
</c:forEach>
</ui:composition>
The code loops through the menu items at the current level and then calls itself, passing the sub-menu of the next level as a parameter, and then goes on and on, until it walks through the whole tree structure.